![8a989018f97850c4ba960ceb870d2cfa.png](https://i-blog.csdnimg.cn/blog_migrate/e35cbacb16c7086ae7aafef32aa5f7fb.jpeg)
原文发表于Unity中国论坛 ,如果对你有帮助请关注我!
Unity游戏如何在iOS上调用Facebook原生对话框分享图片 - Unityunity.cn![0af1b5649e2e56232bc29e5204e8f3a6.png](https://i-blog.csdnimg.cn/blog_migrate/cc24df55cd733566c5d72a8ae567cf57.png)
手头上的一个游戏项目需要实现截屏并分享到Facebook的功能,但Facebook Unity SDK提供的两个接口:FB.FeedShare() 和 FB.ShareLink,前者会弹出一个Web登录提示框,用户需要登录后才能分享,用户体验流程繁琐。后者虽然不需要登录就可以调用Facebook原生的分享对话框,但只能分享链接不能直接分享本地图片。这意味着如何要实现将屏幕截图分享到Facebook的功能,我们需要先将本地截屏的图片上传到某个图床,获取图片的链接然后再调用FB.ShareLink() 才行。这个方法虽然勉强也可以实现分享图片的功能,但过程仍然繁琐,而且分享到Facebook的图片是以外链网页的缩略图方式展示的,要查看全图还要再次点击打开,也不大符合我们的要求。进一步研究了Facebook SDK的文档,发现iOS SDK提供了直接调用Facebook原生对话框分享图片的功能,于是有了下面的Objectiv-C插件的解决方案。
开始之前
本文中的代码在Unity3D 2019.3.6f 以及Xcode 11.3.1中调试通过
开始之前,请下载并导入最新版本的Facebook SDK for Unity https://developers.facebook.com/docs/unity/downloads/
在Assets/Plugins/iOS目录下创建Objective-C插件
我们需要创建三个文件放在Assets/Plugins/iOS目录下,这样在Unity打包输出xcode工程项目时会自动将文件拷贝到工程的Libraries/Plugins/iOS目录并添加正确的引用。这三个文件的作用分别如下:
- NativeFBShareDelegate.h : 定义继承自FBSDKSharingDelegate的回调接口,接受Facebook原生对话框分享成功、取消、错误消息回调。
- NativeFBShareDelegate.m:回调接口的实现代码,收到Facebook原生对话框分享的消息回调后,使用UnitySendMessage() 方法把结果发送给Unity C#脚本。
- NativeFBShare.mm:定义C#中调用的Native Plugin接口方法,调用Facebook iOS SDK打开原生分享对话框(注意这个文件的后缀名要使用.mm)
NativeFBShareDelegate.h 源代码
#import <FBSDKShareKit/FBSDKShareKit.h>
@interface NativeFBShareDelegate : NSObject<FBSDKSharingDelegate>
+ (instancetype)instanceWithRequestID:(int)requestID;
@end
NativeFBShareDelegate.m 源代码
#import <Foundation/Foundation.h>
#import "NativeFBShareDelegate.h"
#import "FBUnityUtility.h"
#import "UnityInterface.h"
//Unity 中接收回调消息的游戏对象名称
const char* const GAME_OBJECT_NAME = "FBShareButton";
//Unity 中处理回调消息的方法名称
const char* const FBUnityMethodName_OnFacebookShareNativeCallback = "OnFacebookShareNativeCallback";
static NSMutableArray *g_instances;
@implementation NativeFBShareDelegate {
int _requestID;
}
+ (void)initialize
{
if (self == [NativeFBShareDelegate class]) {
g_instances = [NSMutableArray array];
}
}
- (void)complete
{
[g_instances removeObject:self];
}
+ (instancetype)instanceWithRequestID:(int)requestID
{
NativeFBShareDelegate *instance = [[NativeFBShareDelegate alloc] init];
instance->_requestID = requestID;
[g_instances addObject:instance];
return instance;
}
#pragma mark - FBSDKSharingDelegate
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results
{
NSLog(@"FBShareComplete");
//分享成功,返回字符串“success”
UnitySendMessage(GAME_OBJECT_NAME, FBUnityMethodName_OnFacebookShareNativeCallback, "success");
[self complete];
}
- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error
{
NSLog(@"FBShareError");
//分享发生错误时,返回字符串“error”
UnitySendMessage(GAME_OBJECT_NAME, FBUnityMethodName_OnFacebookShareNativeCallback, "error");
[self complete];
}
- (void)sharerDidCancel:(id<FBSDKSharing>)sharer
{
NSLog(@"FBShareCancelled");
//用户取消了分享,返回字符串“cancelled”
UnitySendMessage(GAME_OBJECT_NAME, FBUnityMethodName_OnFacebookShareNativeCallback, "cancelled");
[self complete];
}
@end
NativeFBShare.mm 源代码
#import <FBSDKShareKit/FBSDKShareKit.h>
#import "FBUnitySDKDelegate.h"
#import "FBUnityUtility.h"
#import "NativeFBShareDelegate.h"
#ifdef UNITY_4_0 || UNITY_5_0
#import "iPhone_View.h"
#else
extern UIViewController* UnityGetGLViewController();
#endif
extern "C" void _NativeFacebookShare( const char* imagePath )
{
NSString *imgPath = [[NSString alloc]initWithUTF8String:imagePath];
NSLog(@"_NativeFacebookShare local image path: %@", imgPath);
UIImage *image = [UIImage imageWithContentsOfFile:imgPath];
FBSDKSharePhoto *photo = [[FBSDKSharePhoto alloc] init];
photo.image = image;
photo.userGenerated = YES;
FBSDKSharePhotoContent *content = [[FBSDKSharePhotoContent alloc] init];
content.photos = @[photo];
UIViewController *rootViewController = UnityGetGLViewController();
FBSDKShareDialog *dialog = [[FBSDKShareDialog alloc] init];
dialog.fromViewController = rootViewController;
dialog.shareContent = content;
dialog.mode = FBSDKShareDialogModeAutomatic;
NativeFBShareDelegate *delegate = [NativeFBShareDelegate instanceWithRequestID:1];
dialog.delegate = delegate;
NSError *error;
if (![dialog validateWithError:&error]) {
[FBUnityUtility sendErrorToUnity:FBUnityMessageName_OnShareLinkComplete error:error requestId:1];
}
if (![dialog show]) {
[FBUnityUtility sendErrorToUnity:FBUnityMessageName_OnShareLinkComplete errorMessage:@"Failed to show share dialog_" requestId:1];
}
}
在Unity 中调用Facebook的原生分享对话框
在Unity中,可以用下面的C#代码调用刚才实现的iOS原生插件接口:
#if UNITY_IOS || UNITY_IPHONE
[System.Runtime.InteropServices.DllImport( "__Internal" )]
private static extern bool _NativeFacebookShare(string localImagePath);
#endif
我们在Unity中创建一个Button,如下图:
![eb5573dfab7a82b8ec2b28f42e567cd7.png](https://i-blog.csdnimg.cn/blog_migrate/f446693d0cd8b9f256cdd18d7c6c966b.png)
注意Button命名为FBShareButton,这个GameObject名字我们稍后还会用到),挂上下面的脚本,即可实现截屏并分享到Facebook的功能。
using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class FacebookShareButton : MonoBehaviour
{
void Awake() {
GetComponent<Button>().onClick.AddListener(_OnButtonClick);
}
private void _OnButtonClick()
{
this.transform.localScale = Vector3.zero;
StartCoroutine(_ShareOnFacebook());
}
private IEnumerator _ShareOnFacebook()
{
string screenshotFileName = "screenshot.png";
string screenshotFilePath = Path.Combine(Application.persistentDataPath,
screenshotFileName);;
if(File.Exists(screenshotFilePath)){
File.Delete(screenshotFilePath);
}
yield return new WaitForEndOfFrame();
ScreenCapture.CaptureScreenshot(screenshotFileName);
while(!File.Exists(screenshotFilePath)){
yield return null;
}
#if UNITY_IOS || UNITY_IPHONE
_NativeFacebookShare(screenshotFilePath);
#elif UNITY_ANDROID
//TODO: Calling Android native plugin to share on Facebook
#endif
}
#if UNITY_IOS || UNITY_IPHONE
[System.Runtime.InteropServices.DllImport( "__Internal" )]
private static extern bool _NativeFacebookShare(string localImagePath);
#endif
下面是在iPhone真机上运行的结果
![6cea2c474dac351ff15fe615e147563e.png](https://i-blog.csdnimg.cn/blog_migrate/c15987ce60371c1795ed1c98f056f884.jpeg)
获取分享结果的回调通知
有时我们需要知道Facebook分享的结果来实现一些功能,比如如果用户分享失败,则弹出对话框让用户重试一遍。为了实现这个功能,我们在NativeFBShareDelegate.h和NativeFBShareDelegate.m中定义并实现了FBSDKSharingDelegate的回调接口,并在NativeFBShare.mm中创建了这个delegate的实例并注册到FBSDKShareDialog,在收到Facebook原生对话框分享的消息回调后,再使用UnitySendMessage() 方法把结果发送给Unity C#脚本。
UnitySendMessage是Unity提供的一个工具方法,可以从iOS Native Plugin向Unity 游戏对象发送消息。这个方法的签名如下:
void UnitySendMessage(const char* obj, const char* method, const char* msg);
其中第一个参数是接受这个消息的游戏对象名称,第二个参数是这个对象上所绑定的脚本接受回调的方法名称,第三个参数是发送的消息内容,只能是字符串。
在本文前面给出的示例代码中
- 我们接收消息的游戏对象名字为FBShareButton
- 处理回调消息的方法名称是OnFacebookShareNativeCallback(string)
- 用户分享成功返回“success”,发生错误返回“error”,取消返回“cancelled”
我们给FacebookShareButton.cs脚本添加OnFacebookShareNativeCallback(string)方法来接收分享结果的回调消息。
private Text m_ResultText;
void Start()
{
m_ResultText = this.transform.Find("Text").GetComponent<Text>();
m_ResultText.text = "";
}
public void OnFacebookShareNativeCallback(string result)
{
Text shareResult = GetComponent<Text>();
if(string.Equals(result, "success"))
{
shareResult.text = "FB Share Result: Succeed";
}
else if(string.Equals(result, "cancelled"))
{
shareResult.text = "FB Share Result: Cancelled";
}
else
{
shareResult.text = "FB Share Result: Error";
}
}
下面是在iPhone上运行的结果
![06b80d18edc7025fe5b4da207be147a3.png](https://i-blog.csdnimg.cn/blog_migrate/82280a40c4b298ffb32271651ece139f.jpeg)
参考资料
Unity3D关于构建iOS上Native Plugin的官方文档
Facebook Sharing on iOS