Unity游戏如何在iOS上调用Facebook原生对话框分享图片
手头上的一个游戏项目需要实现截屏并分享到Facebook的功能,但Facebook Unity SDK提供的两个接口:FB.FeedShare() 和 FB.ShareLink,前者会弹出一个Web登录提示框,用户需要登录后才能分享,用户体验流程繁琐。后者虽然不需要登录就可以调用Facebook原生的分享对话框,但只能分享链接不能直接分享本地图片。这意味着如何要实现将屏幕截图分享到Facebook
·
手头上的一个游戏项目需要实现截屏并分享到Facebook的功能,但Facebook Unity SDK提供的两个接口:FB.FeedShare() 和 FB.ShareLink,前者会弹出一个Web登录提示框,用户需要登录后才能分享,用户体验流程繁琐。后者虽然不需要登录就可以调用Facebook原生的分享对话框,但只能分享链接不能直接分享本地图片。这意味着如何要实现将屏幕截图分享到Facebook的功能,我们需要先将本地截屏的图片上传到某个图床,获取图片的链接然后再调用FB.ShareLink() 才行。这个方法虽然勉强也可以实现分享图片的功能,但过程仍然繁琐,而且分享到Facebook的图片是以外链网页的缩略图方式展示的,要查看全图还要再次点击打开,也不大符合我们的要求。进一步研究了Facebook SDK的文档,发现iOS SDK提供了直接调用Facebook原生对话框分享图片的功能,于是有了下面的Objectiv-C插件的解决方案。
1 开始之前
开始之前,请下载并导入最新版本的Facebook SDK for Unity https://developers.facebook.com/docs/unity/downloads/
本文中的代码在Unity3D 2019.3.6f 以及Xcode 11.3.1中调试通过。
2 在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)
<u> NativeFBShareDelegate.h 源代码 </u>
#import <FBSDKShareKit/FBSDKShareKit.h>
@
interface
NativeFBShareDelegate
:
NSObject
<
FBSDKSharingDelegate
>
+
(
instancetype
)
instanceWithRequestID
:
(
int
)
requestID
;
@end
<u> NativeFBShareDelegate.m 源代码 </u>
#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
<u> NativeFBShare.mm 源代码</u>
#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
]
;
}
}
3 在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,如下图:

注意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真机上运行的结果

4 获取分享结果的回调通知
有时我们需要知道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上运行的结果

5 参考资料
更多推荐
所有评论(0)