#if defined(__cplusplus)
extern "C"{
#endif
// 获取系统语言
extern char *GetLanguage();
// 开始震动
extern void StartVibration(char *param);
// 是否是全面屏
extern bool IsFullSecreen();
// Unity iOS 字符串内存管理
extern char* CharMemoryManagement(NSString *param);
#if defined(__cplusplus)
}
#endif
#if defined(__cplusplus)
extern "C"{
#endif
char *GetLanguage()
{
NSString *str = [Tools GetLanguage];
return CharMemoryManagement(str);
}
void StartVibration(char *param)
{
[Tools StartVibration:[NSString stringWithUTF8String:param]];
}
bool IsFullSecreen()
{
return [Tools IsFullSecreen];
}
// 如果方法返回的是字符串,需要使用该方法将字符串转为char
char* CharMemoryManagement(NSString *text)
{
char* ret = nullptr;
ret = (char*) malloc([text length] + 1);
memcpy(ret,[text UTF8String],([text length] + 1));
return ret;
}
#if defined(__cplusplus)
}
#endif
#if UNITY_IOS && !UNITY_EDITOR
[DllImport("__Internal")] private static extern string GetLanguage();
[DllImport("__Internal")] private static extern bool IsFullSecreen();
[DllImport("__Internal")] private static extern void StartVibration(string param);
#endif
#region Unity to iOS
public string IOSGetLanguage()
{
#if UNITY_IOS && !UNITY_EDITOR
return GetLanguage();
#else
return "";
#endif
}
public void IOSStartVibration(long time)
{
#if UNITY_IOS && !UNITY_EDITOR
StartVibration(time.ToString());
#endif
}
public bool IOSIsFullSecreen()
{
#if UNITY_IOS && !UNITY_EDITOR
return IsFullSecreen();
#else
return false;
#endif
}
// --------- 某个.mm文件中 ---------
#if defined(__cplusplus)
extern "C"{
#endif
extern void UnitySendMessage(const char *, const char *, const char *);
#if defined(__cplusplus)
}
#endif
// --------- 需要通知Unity的iOS类中 ---------
- (void)didReceiveReward {
// 在iOS的某个方法中,向Unity发送消息
UnitySendMessage("iOSLibraryUnity", "OnDidReceiveReward", "收到奖励");
}
// --------- Unity中挂在节点上的脚本,用来接收通知 ---------
private void Start()
{
// 脚本挂载的节点名必须和UnitySendMessage发送时填的一样
this.name = "iOSLibraryUnity";
}
private void OnDidReceiveReward(string msg)
{
// 接收到iOS通知
Debug.log(msg);
}
Unity要在iOS平台发布,需要先生成Xcode工程,通常生成Xcode工程后我们还需要修改很多的配置,添加原生代码等, 而这些是可以通过cs脚本修改的,比如修改Xcode工程的plist、添加Framework库、拷贝文件到iOS工程、插入代码等
<dependencies>
<iosPods>
<iosPod name="AFNetworking" version="4.0.1"/>
<iosPod name="SDWebImage" version="5.8.4"/>
<iosPod name="Masonry" version="1.1.0"/>
<iosPod name="YYModel" version="1.0.4"/>
</iosPods>
</dependencies>
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using UnityEditor.XCodeEditor;
public static class BuildiOS
{
[PostProcessBuild(100)]
public static void OnPostprocessBuild(BuildTarget buildTarget, string buildPath)
{
if (buildTarget != BuildTarget.iOS)
return;
var mProjectPath = PBXProject.GetPBXProjectPath(buildPath);
var mProject = new PBXProject();
mProject.ReadFromString(File.ReadAllText(mProjectPath));
var mTargetGUID = GetPBXProjectTargetGUID(mProject);
var mFrameworkGUID = GetPBXProjectUnityFrameworkGUID(mProject);
var mPlistPath = Path.Combine(buildPath, "Info.plist");
// 修改Plist
PlistModify(mPlistPath);
// 添加系统库
SystemFrameworkAdd(mProject, mFrameworkGUID);
// 添加文件
FilesAdd(mProject, mTargetGUID, buildPath, mProjectPath);
// 插入代码
UnityAppControllerCodesAdd(buildPath);
}
#if UNITY_2019_3_OR_NEWER
private static string GetPBXProjectTargetGUID(PBXProject project)
{
return project.GetUnityMainTargetGuid();
}
private static string GetPBXProjectUnityFrameworkGUID(PBXProject project)
{
return project.GetUnityFrameworkTargetGuid();
}
#else
private static string GetPBXProjectTargetGUID(PBXProject project)
{
return project.TargetGuidByName(PBXProject.GetUnityTargetName());
}
private static string GetPBXProjectUnityFrameworkGUID(PBXProject project)
{
return GetPBXProjectTargetGUID(project);
}
#endif
}
private static void PlistModify(string plistPath)
{
var plist = new PlistDocument();
plist.ReadFromFile(plistPath);
// plist中添加一个字符串类型的key 如隐私设置
plist.root.SetString("NSLocationAlwaysAndWhenInUseUsageDescription",
"$(PRODUCT_NAME) needs to get the location. I hope you agree.";
// plist中添加一个布尔的key
plist.root.SetBoolean("CADisableMinimumFrameDuration", false);
// plist中添加一个字典的key 如ATS设置
PlistElementDict dict = plist.root.CreateDict("NSAppTransportSecurity");
dict.SetBoolean("NSAllowsArbitraryLoads", true);
// 最后保存plist
plist.WriteToFile(plistPath);
}
private static void SystemFrameworkAdd(PBXProject project, string mFrameworkGUID)
{
string[] FRAMEWORKS_TO_ADD = {
"libz.dylib",
"libc++.dylib",
"Security.framework",
"SystemConfiguration.framework",
};
foreach (var framework in FRAMEWORKS_TO_ADD)
{
project.AddFrameworkToProject(mFrameworkGUID, framework, false);
}
}
private static void SystemLibAdd(PBXProject project, string targetGuid, string lib)
{
string fileGuid = project.AddFile("usr/lib/" + lib, "Frameworks/" + lib, PBXSourceTree.Sdk);
project.AddFileToBuild(targetGuid, fileGuid);
}
private static void FilesAdd(PBXProject project, string mTargetGUID, string buildPath, string projectPath)
{
string ResourcePath = "Assets/文件夹路径";
XcodeDirectoryProcessor copy = new XcodeDirectoryProcessor();
copy.CopyAndAddBuildToXcode(project, mTargetGUID, ResourcePath, buildPath, "Xcode中的文件夹名称");
File.WriteAllText(projectPath, project.WriteToString());
}
private static void UnityAppControllerCodesAdd(string buildPath)
{
// 获取Prefix.pch文件
string mPchPath = buildPath + "/Classes/Prefix.pch";
UnityEditor.XCodeEditor.XClass Pch = new UnityEditor.XCodeEditor.XClass(mPchPath);
// 需要插入的代码,例如我们在pch中插入一段引入类的代码
string call = "#import \"output.h\"";
// 代码标记,找到pch文件里面已经存在的代码,我们就可以将需要插入的代码,插入到这行代码下面
string mark = "#include \"UnityInterface.h\"";
// 开始插入代码
Pch.WriteBelow(mark, call);
}
using UnityEngine;
using System.IO;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
public static class ExtensionName
{
public const string META = ".meta";
public const string ARCHIVE = ".a";
public const string FRAMEWORK = ".framework";
public const string BUNDLE = ".bundle";
}
public class XcodeDirectoryProcessor {
/// <summary>
/// 添加编译本地文件到Xcode工程
/// </summary>
/// <param name="pbxProject"></param>
/// <param name="targetGuid"></param>
/// <param name="copyDirectoryPath">源路径</param>
/// <param name="buildPath">拷贝路径</param>
/// <param name="currentDirectoryPath">拷贝路径/currentDirectoryPath</param>
/// <param name="needToAddBuild"></param>
public void CopyAndAddBuildToXcode(PBXProject pbxProject, string targetGuid, string copyDirectoryPath, string buildPath, string currentDirectoryPath, bool needToAddBuild = true){
string unityDirectoryPath = copyDirectoryPath;
string xcodeDirectoryPath = buildPath;
if(!string.IsNullOrEmpty(currentDirectoryPath)){
unityDirectoryPath = Path.Combine(unityDirectoryPath, currentDirectoryPath);
xcodeDirectoryPath = Path.Combine(xcodeDirectoryPath, currentDirectoryPath);
Delete (xcodeDirectoryPath);
Directory.CreateDirectory(xcodeDirectoryPath);
}
foreach (string filePath in Directory.GetFiles(unityDirectoryPath)){
string extension = Path.GetExtension (filePath);
if(extension == ExtensionName.META){
continue;
}
else if(extension == ExtensionName.ARCHIVE){
pbxProject.AddBuildProperty(
targetGuid,
"LIBRARY_SEARCH_PATHS",
"$(PROJECT_DIR)/" + currentDirectoryPath
);
}
string fileName = Path.GetFileName (filePath);
string copyPath = Path.Combine (xcodeDirectoryPath, fileName);
if(fileName[0] == '.'){
continue;
}
File.Delete(copyPath);
File.Copy(filePath, copyPath);
if(needToAddBuild){
string relativePath = Path.Combine(currentDirectoryPath, fileName);
pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
}
}
//遍历文件夹
foreach (string directoryPath in Directory.GetDirectories(unityDirectoryPath)){
string directoryName = Path.GetFileName (directoryPath);
bool nextNeedToAddBuild = needToAddBuild;
if(directoryName.Contains(ExtensionName.FRAMEWORK) || directoryName.Contains(ExtensionName.BUNDLE) ||
directoryName == "Unity-iPhone"){
nextNeedToAddBuild = false;
}
CopyAndAddBuildToXcode (
pbxProject, targetGuid,
copyDirectoryPath, buildPath, Path.Combine(currentDirectoryPath, directoryName),
nextNeedToAddBuild
);
if(directoryName.Contains(ExtensionName.FRAMEWORK) || directoryName.Contains(ExtensionName.BUNDLE)){
string relativePath = Path.Combine(currentDirectoryPath, directoryName);
pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
pbxProject.AddBuildProperty(
targetGuid,
"FRAMEWORK_SEARCH_PATHS",
"$(PROJECT_DIR)/" + currentDirectoryPath
);
}
}
}
/// <summary>
/// 拷贝目录(拷贝时候会删除copyPath)
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="copyPath"></param>
public void CopyAndReplace(string sourcePath, string copyPath)
{
Delete (copyPath);
Directory.CreateDirectory(copyPath);
foreach (var file in Directory.GetFiles(sourcePath)){
File.Copy(file, Path.Combine(copyPath, Path.GetFileName(file)));
}
foreach (var dir in Directory.GetDirectories(sourcePath)){
CopyAndReplace(dir, Path.Combine(copyPath, Path.GetFileName(dir)));
}
}
/// <summary>
/// 删除目录
/// </summary>
/// <param name="targetDirectoryPath"></param>
public void Delete(string targetDirectoryPath){
if (!Directory.Exists (targetDirectoryPath)) {
return;
}
string[] filePaths = Directory.GetFiles(targetDirectoryPath);
foreach (string filePath in filePaths){
File.SetAttributes(filePath, FileAttributes.Normal);
File.Delete(filePath);
}
string[] directoryPaths = Directory.GetDirectories(targetDirectoryPath);
foreach (string directoryPath in directoryPaths){
Delete(directoryPath);
}
Directory.Delete(targetDirectoryPath, false);
}
}
#endif
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有