xcode学习glfw 的 custom project template

最近在看learn opengl,每次都要配置opengl的项目有点烦,例如,需要添加framework,需要增加search path等,然后发现xcode可以支持项目模板。但是有一点比较烦就是每次升级系统或者升级xcode配置都不见了,所以记个笔记。这个也是自己摸索和找参考资料写的,部分是自己的理解,可能存在错误和遗漏。

xcode的project template位置在

/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/

opengl学习项目一般是mac OS系统的命令行项目,所以在上述的文件夹下面的macOS文件夹下添加OpenGL文件夹。

cd macOS
sudo mkdir OpenGL

copy Application/Command Line Tool.xctemplate到OpenGL目录下,修改项目名字为Base OpenGL.xctemplate。
Base OpenGL.xctemplate里面此时有三个文件

TemplateIcon.png
TemplateIcon@2x.png
TemplateInfo.plist

两个png文件是用来做项目的图标的,是不是修改随意。
主要考虑TemplateInfo.plist文件,如果在原文件夹不能修改,可以复制到别的文件夹,例如Desktop,修改完再覆盖回去。一般来说,TemplateInfo.plist如下

Kind是模板类型,不需要修改
Identifier是模板的唯一标志符,自己新加的,必须修改
Ancestors 用来表明继承自某些模板,不需要修改
Concrete 必须是1或者YES,表示不是抽象的模板,需要在创建时展示。
SortOrder 应该是用来设置排序
Description 模板描述,可以改成自己需要的文案
Targets 我的理解是用来创建项目的产品类型和文件夹配置之类的,一般不用修改。因为opengl学习一般需要读取相对目录(例如Resources)下的shader或者图片文件,可以修改CopyFiles如下

DstSubfolderSpec 设置成7,RunOnlyForDeploymentPostprocessing 设置成NO,体现在项目文件中应该是类似如下

Options 语言类型以及项目配置

因为opengl我一般都是c++,所以不需要oc,swift,c的语言类型可以删掉。
第一,Values删除Object-c,swift,c
第二,Default 默认语言改成需要的C++
第三,Units也删除oc,swift,c的选项
另外,因为openGL配置一般需要添加search path,可以在如上图的Units/C++/Project/SharedSettings下添加 LIBRARY_SEARCH_PATHS 和 HEADER_SEARCH_PATHS,增加自己对应项目的库文件夹地址和header文件夹地址。我配置的glfw_lib和glfw_include分别在Preferences下的custom path配置好了。
frameworks和dylib也可以在这里配置,在如上图的Units/C++/Targets/Item 0/Frameworks添加 Cocoa,IOKit,CoreVideo,OpenGL这4个framework。在Units/C++/Targets/Item 0/Libraries下添加自己对应的glfw和glew的lib库,可以在/usr/local/lib/这个文件夹下找到具体的dylib的名字,例如我的版本是libglfw.3.3.dylib 和 libGLEW.2.1.0.dylib



第四,Nodes和Definitions,这里主要是定义模板里的文件和文件夹,以及main文件。Nodes是Array类型,Defintions是Dictionary类型。
这里可以分为三类,第一类是文件或者文件夹,第二类是main.cpp文件里的最顶部的注释、头文件、还有function的声明等,第三类是main.cpp里文件的functions。
文件或者文件夹一般是在Nodes里添加一个item,例如为ResourcesShader.cpp,在Definitions里一般添加一个key为上面item名字的Dictionary,添加一个key为Path的string,value为实际的相对目录。
注释和头文件等也就是Nodes里添加一个item,例如main.cpp:comments或者main.cpp:include,注意comments一般都是自动生成,不需要在Definitions额外定义了。main.cpp:include在Definitions里添加String,内容自己定义即可。
main.cpp里的function,在Nodes里声明为main.cpp:function_name:content,在Definitions里定义实际的main.cpp:function_name:content的内容,还有main.cpp:function_name对应方法的的Beginning 和 End,还有Indent。
举个🌰,类似下面的一个function

void processInput(GLFWwindow* window) {
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);
}

在Nodes里添加一个 item,格式为string
main.cpp:processInput:content
在Definitions里添加一个key为main.cpp:processInput:content的string,value为

    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);

在Definitions里添加一个Dictionary,key为main.cpp:processInput,实际一般如下

Definitions 我的理解是全局的一些定义,例如Options里如果有C和C++,有部分main的定义可以放至此处,可以参考xcode自带的Command Line Tool.xctemplate

参考:
https://medium.com/overapp-ios/create-xcode-templates-c968d4b43f7b

Unity Android Crash 简单定位

官方文档Symbolicate Android Crash

unity安卓项目有时候会出现安卓闪退,崩溃出来的堆栈类似如下

2020-01-13 15:40:47.554 12602-12739/xx.xx.xx.xx E/CRASH:

#00 pc 000000000000069c [vdso] () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#01 pc 000000000001ceb8 /system/lib64/libc.so (memset+136) 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#02 pc 0000000000a5abe4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#03 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#04 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#05 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#06 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#07 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#08 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#09 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#10 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#11 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#12 pc 0000000000a5ac00 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#13 pc 0000000000a38fc4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#14 pc 0000000000a4ac54 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#15 pc 0000000000a4aaa8 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#16 pc 00000000004efae0 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libunity.so (_ZN11Marshalling17ArrayUnmarshallerINS_18StringArrayElementES1_E18ArrayFromContainerISt6vectorIN4core12basic_stringIcNS5_20Stri ngStorageDefaultIcEEEESaIS9_EELb1EE14UnmarshalArrayERKSB_+148) 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#17 pc 00000000004ef170 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libunity.so (_Z48AssetBundleManifest_CUSTOM_GetDirectDependenciesP12Il2CppObjectP12Il2CppString+244) 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#18 pc 0000000000f6a378 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#19 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#20 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#21 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#22 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#23 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#24 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#25 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#26 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#27 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#28 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#29 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#30 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so () 2020-01-13 15:40:47.555 12602-12739/xx.xx.xx.xx E/CRASH:

#31 pc 0000000000f6a3f4 /data/app/xx.xx.xx.xx-tcfkPS-N3WH5aQuqMs6lVA==/lib/arm64/libil2cpp.so ()

unity的符号表文件一般在导出安卓项目时生成的symbols.zip文件里。
可以通过使用addr2line工具将上面崩溃堆栈的内存地址转成具体的方法,addr2line在ndk的文件夹下找到(以mac版本r16b为例):
64位:android-ndk-r16b/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line
32位:android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line

例如

./aarch64-linux-android-addr2line -f -C -e   libil2cpp.sym 0000000000f6a378 0000000000f6a3f4

执行结果类似如下

BundleManager_LoadTask_mD57E35306E924ABDF527B9ABC7E4C1C412484CAA
...../StagingArea/Il2Cpp/il2cppOutput/Bulk_Assembly-CSharp_0.cpp:39598
BundleManager_LoadTask_mD57E35306E924ABDF527B9ABC7E4C1C412484CAA
..../StagingArea/Il2Cpp/il2cppOutput/Bulk_Assembly-CSharp_0.cpp:39653

unity 异步加载动画与AlwaysAnimate裁剪冲突

最近项目发现一个奇怪问题,就是异步加载某个模型,然后模型本身又带有动画的时候,会出现动画刚加载好时不是直接进入Entry指向的状态,而是会卡一帧。经查发现这些动画的裁剪方式都是AlwaysAnimate,没有找到原因,默默将模型默认的裁剪改回CullUpdateTransforms,然后在加载完后延迟一帧再设置裁剪方式就解决。

unity接入unity版本sdk和android版本sdk冲突问题(firebase和gp登录)

unity版本2018.4
play-services-resolver_v1.2.124.0

gradle版本3.4
targetSdkVersion 28

unity要接入sdk,先在Firebase去下载了unity版本的Analysis的package导入,测试apk通过,希望接入G+登录时,因为没有专门给unity的版本,所以直接去google的官网,在安卓工程的build.gradle里添加了

implementation 'com.google.android.gms:play-services-auth:17.0.0'

然后发现这个库和unity那边导出的一堆jar和aar出现了类似于Duplicate class android.support.v4.app.INotificationSideChannel$Stub found in modules classes.jar (androidx.core.core-1.0.0.aar) and classes.jar (androidx.core:core:1.0.0)的报错等。

可以通过删除unity导出的对应aar和jar来解决,也可以通过在implementation google的库的时候,exclude掉冲突的部分解决,如下

implementation ('com.google.android.gms:play-services-auth:17.0.0') {
    exclude group: 'androidx.core',module:'core'
    exclude group: 'androidx.annotation',module:'annotation'
    exclude group: 'androidx.arch.core',module:'core-runtime'
    exclude group: 'androidx.asynclayoutinflater',module:'asynclayoutinflater'
    exclude group: 'androidx.arch.core',module:'core-common'
    exclude group: 'androidx.collection',module:'collection'
    exclude group: 'androidx.coordinatorlayout',module:'coordinatorlayout'
    exclude group: 'androidx.cursoradapter',module:'cursoradapter'
    exclude group: 'androidx.documentfile',module:'documentfile'
    exclude group: 'androidx.drawerlayout',module:'drawerlayout'
    exclude group: 'androidx.fragment',module:'fragment'
    exclude group: 'androidx.interpolator',module:'interpolator'
    exclude group: 'androidx.legacy',module:'legacy-support-core-ui'
    exclude group: 'androidx.legacy',module:'legacy-support-core-utils'
    exclude group: 'androidx.lifecycle',module:'lifecycle-viewmodel'
    exclude group: 'androidx.lifecycle',module:'lifecycle-common'
    exclude group: 'androidx.lifecycle',module:'lifecycle-livedata'
    exclude group: 'androidx.loader',module:'loader'
    exclude group: 'com.google.android.gms',module:'play-services-basement'
    exclude group: 'com.google.android.gms',module:'play-services-base'
    exclude group: 'com.google.android.gms',module:'play-services-tasks'
}

前阵子升级fb sdk,因为Unity版本过老,facebook unity sdk已经不再支持,只能重新接入安卓版本。更新的时候找到了一个更简单有效的方式,在Unity的Assets目录找个地方塞个Dependencies.xml文件,注意该文件必须放在Editor文件夹下,格式类似如下

<?xml version="1.0" encoding="utf-8"?>
<dependencies>
    <androidPackages>
        <androidPackage spec="com.facebook.android:facebook-android-sdk:16.0.0" />
    </androidPackages>
</dependencies>

然后在Android Resolver里Resolve一下依赖,如果有个别aar版本多版本都存在,可以先Delete Resolved Libraries,再Resolve即可。

修改Unity的UI的默认shader

本文学习自宣雨松大大的《Unity 3D游戏开发》。

Unity的UI元素例如Image是不需要指定材质,UGUI提供了默认的材质和Shader,这个Shader是比较全面各种情况都适用。但是其实实际开发中可以进行一些取舍,例如去掉颜色的乘法和背面渲染。我们可以取出Unity的内置Shader源码,对其进行一些修改。但是注意这个修改会不仅仅对图片生效,也会对Text生效,如果Text没有做成通用Prefab,则建议不要进行修改,或者重写一下生成Text的菜单。

  • 1、在Unity的下载页选择对应版本的Build in Shaders,我下的版本是builtin_shaders-2018.4.2f1,解压缩后,UI的默认Shader就是DefaultResourcesExtra/UI/UI-Default.shader

  • 2、找到Shader里的Cull Off,改成Cull Back,表示剔除背面裁剪

  • 3、在片段着色器方法frag里找到下面代码
    half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;改成 half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd);

  • 4、在Unity的Project Settings下面的Graphic栏目,在Always include shaders里的UI/Default修改成绑定上面的Shader,重启Unity后生效。

  • 5、新建一个空白材质球,把原本的UI-Default.shader赋予他,但是注意修改一下该Shader的路径,例如我的修改成Default_Unity。将该Shader也绑定到Always include shaders。

附上Text创建重写代码


[MenuItem("GameObject/UI/Text")] static void CreateText() { if(Selection.activeTransform) { if(Selection.activeTransform.GetComponentInParent<Canvas>()) { Text text = new GameObject("text").AddComponent<Text>(); //Change to your shader setting path /* Shader "UI/Default_Unity" { Properties { ... */ Material mat = new Material(Shader.Find("UI/Default_Unity")); text.material = mat; text.transform.SetParent(Selection.activeTransform, false); Selection.activeTransform = text.transform; } } }

上图中两张图片(感谢主子免费出场),左边的是用的Unity的原始的Shader,即自己设置了材质球,材质球绑定了的UI/Default_Unity,右边的是修改过的默认的Unity的UI shader,文本控件也是自行设置了材质球。