...menustart
- 工作相关 Unity 笔记
- PostProcessBuild
- Unity Archive
- isDebug
- comments in inspector
- open new OSX unity instance
- change the order or child object
- AB: build AssetBundles
- get the name of all AssetBundles
- inform when Asset changed
- clean Asset Bundle name
- set Asset Bundle name
- UGUI event callback
- 获取脚本名字
- UI Text 真实宽高
- iOS9 App Slicing
- 遍历目录
- native plugin bool 返回值问题
- Unity Engine/Editor 源码
- 调用父类 override 方法
- 优化
- Build from command line
- 关闭 Debug.Log 日志
- IOS - Could not produce class with ID
- check if animation is end
- iOS , overwrite UnityAppController
- check 32-bit or 64-bit
- RectTransform
- Change UI Opacity , Alpha
- ClearChildren
- Force canvas sorting order
- change Image's Source Image
- c/c++ plugin Log
- detect whether an object has been destroyed ?
- ScrollView 实践
- reset scroll rect content to original postion
- Dictionary iteration
- AES , encrypt by python, decrypt by c#
- http request under proxy
- convert Input.mouseposition to object local space
...menuend
PostProcessBuild 这个 attribute 修饰的 static function 会在 Unity 建置完之后被呼叫。这个函式需要接受两个参数,一个是 BuildTarget enum ,代表建置的目标平台。另一个是 string 是建置的目标目录。
使用 PostProcessBuild 设定 Unity 产生的 Xcode Project
- PS:
OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
的参数 pathToBuiltProject , 使用 cmd line编译时,不包含路径
https://unity3d.com/get-unity/download/archive
Debug.isDebugBuild
[Header("Button Settings")]
[Tooltip("Arbitary text message")]
open -na Unity
transform.SetSiblingIndex
transform.GetSiblingIndex
[MenuItem ("Assets/Build AssetBundles")]
public static void BuildAllAssetBundles ()
{
// clean all exist asset bundle name
ClearAssetBundlesName.clean ();
// re-set asset bundle
SetAssetBundleName.setNames();
// create out folder
string outputPath = "./OutAssetBundles" ;
//Path.Combine (AssetBundlesOutputPath,Platform.GetPlatformFolder(EditorUserBuildSettings.activeBuildTarget));
if (!Directory.Exists (outputPath))
{
Directory.CreateDirectory(outputPath);
}
// build pipline
BuildPipeline.BuildAssetBundles ( outputPath );
ClearAssetBundlesName.clean ();
AssetDatabase.Refresh ();
}
BuildAssetBundleOptions:
BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.DeterministicAssetBundl
ChunkBasedCompression 适合实时动态加载
public class GetAssetBundleNames
{
public static void GetNames ()
{
var names = AssetDatabase.GetAllAssetBundleNames();
foreach (var name in names)
Debug.Log ("AssetBundle: " + name);
}
}
// info when asset changed
public class MyPostprocessor : AssetPostprocessor {
void OnPostprocessAssetbundleNameChanged ( string path,
string previous, string next) {
Debug.Log("AB: " + path + " old: " + previous + " new: " + next);
}
}
public class ClearAssetBundlesName {
public static void clean()
{
int length = AssetDatabase.GetAllAssetBundleNames ().Length;
Debug.Log ( "---- existing ab name num:" + length);
string[] oldAssetBundleNames = new string[length];
for (int i = 0; i < length; i++)
{
oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i];
}
for (int j = 0; j < oldAssetBundleNames.Length; j++)
{
AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j],true);
}
length = AssetDatabase.GetAllAssetBundleNames ().Length;
Debug.Log ( "----- new ab name num:" + length);
}
}
public class SetAssetBundleName {
//*
public static void setNames( ) {
walk( "./Assets" );
}
//*/
static void walk(string source )
{
DirectoryInfo folder = new DirectoryInfo (source);
FileSystemInfo[] files = folder.GetFileSystemInfos ();
int length = files.Length;
for (int i = 0; i < length; i++) {
if(files[i] is DirectoryInfo)
{
walk(files[i].FullName);
}
else
{
if(!files[i].Name.EndsWith(".meta") && !files[i].Name.EndsWith(".cs") )
{
setAssetBundleName (files[i].FullName);
//Debug.Log( files[i].Name ) ;
}
}
}
}
static void setAssetBundleName(string source)
{
string _source = Replace (source);
string _assetPath = "Assets" + _source.Substring (Application.dataPath.Length);
string _assetPath2 = _source.Substring (Application.dataPath.Length + 1);
//Debug.Log (_assetPath);
//在代码中给资源设置AssetBundleName
AssetImporter assetImporter = AssetImporter.GetAtPath (_assetPath);
string assetName = "nofolder";
int indexLastSlash = _assetPath2.LastIndexOf ("/");
if (indexLastSlash > 0)
assetName = _assetPath2.Substring (0, _assetPath2.LastIndexOf ("/"));
else
assetName = _assetPath2 ;
// add suffix to avoid the case: bot res file and folder in a parent folder
assetName += ".unity";
//Debug.Log (assetName);
assetImporter.assetBundleName = assetName;
}
static string Replace(string s)
{
return s.Replace("\\","/");
}
}
Dropdown scriptCameraList = cameraList.GetComponent<Dropdown> ( );
scriptCameraList.onValueChanged.AddListener((int id ) =>
{
cameraChoosed( id );
});
this.GetType().Name
text.preferredWidth
text.preferredHeight
private static void GetDirs(string dirPath, ref List<string> dirs)
{
if ( !Directory.Exists (dirPath))
return;
foreach (string path in Directory.GetFiles(dirPath))
{
//获取所有文件夹中包含后缀为 .prefab 的路径
//if (System.IO.Path.GetExtension(path) == ".prefab")
dirs.Add( path ); // path.Substring(path.IndexOf("Assets"))
//Debug.Log(path.Substring(path.IndexOf("Assets")));
}
if (Directory.GetDirectories(dirPath).Length > 0) //遍历所有文件夹
{
foreach (string path in Directory.GetDirectories(dirPath))
{
GetDirs(path, ref dirs);
}
}
}
[DllImport ("__Internal")]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool carFileExists( string path ) ;
https://bitbucket.org/Unity-Technologies/ui/src/b5f9aae6ff7c2c63a521a1cb8b3e3da6939b191b?at=5.3
base.func( ... )
不需要交互的UI组件, 去掉 ray caster 选项 移动平台,使用 touchInputModule
创建时:
- 加载完后立即AssetBundle.Unload(false),释放AssetBundle文件本身的内存镜像,但不销毁加载的Asset对象
释放时:
- 如果有Instantiate的对象,用Destroy进行销毁
- Resources.UnloadUnusedAssets,释放已经没有引用的Asset
- 如果需要立即释放内存加上GC.Collect()
注意: 尽管guid相同, 不同 ab 实例,会 load出多分asset ,导致内存泄漏
<linker>
<assembly fullname="UnityEngine">
<type fullname="UnityEngine.Animation" preserve="all"/>
<type fullname="UnityEngine.MeshCollider" preserve="all"/>
<type fullname="UnityEngine.AnimationClip" preserve="all"/>
<type fullname="UnityEngine.ParticleSystemRenderer" preserve="all"/>
</assembly>
<assembly fullname="Assembly-CSharp">
<type fullname="MediaPlayerCtrl" preserve="all"/>
</assembly>
</linker>
http://docs.unity3d.com/410/Documentation/ScriptReference/MonoCompatibility.html
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -projectPath "${WORKSPACE}" -executeMethod Build.Build_iOS_Device -quit -logFile /dev/stdout
Debug.logger.logEnabled=false; ???
这是因为你勾选了strip code,一些代码由于检测不到引用就被strip掉了,但是从AssetBundle里加载出来又需要根据ID找到对应代码。
- http://docs.unity3d.com/Manual/ClassIDReference.html 找到ID对应的class
- 在Assets目录下新建文件link.xml,把不该strip掉的类加进去
- 有些类比如 AnimatorController(ID-91)属于Editor包里的,不能用link.xm加回来,可以在Resource下建一个空的prefab,在上面挂一个AnimatorController,打包时留下这个prefab就可以确保这个类不被strip掉了。
<linker>
<assembly fullname="UnityEngine">
<type fullname="UnityEngine.Animation" preserve="all"/>
<namespace fullname="UnityEngine.Audio" preserve="all"/>
</assembly>
<assembly fullname="System">
<type fullname="System.Net.HttpWebRequest" preserve="all"/>
<type fullname="System.Net.WebResponse" preserve="all"/>
</assembly>
<assembly fullname="System">
<namespace fullname="System.Net" preserve="all"/>
<namespace fullname="System.Net.Configuration" preserve="all"/>
</assembly>
<assembly fullname="mscorlib">
<namespace fullname="System.Security.Cryptography" preserve="all"/>
</assembly>
<assembly fullname="Mono.Security">
<namespace fullname="Mono.Security.Protocol.Tls" preserve="all"/>
<namespace fullname="Mono.Security.X509" preserve="all"/>
</assembly>
</linker>
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime > 1 && !animator.IsInTransition(0))
#import "UnityAppController.h"
@interface CustomAppController : UnityAppController
@end
// let unity call CustomAppController , instead of UnityAppController
IMPL_APP_CONTROLLER_SUBCLASS (CustomAppController)
@implementation CustomAppController
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
[super application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
@end
if (IntPtr.Size == 4) {
//32 Bit
}
else if (IntPtr.Size == 8)
{
//64 Bit
}
rectTrans.offsetMin= new Vector2(-11, -12 );
rectTrans.offsetMax= new Vector2(13, 14 );
等价:
Left: -11
Button: -12
Right: -13
Top: -14
AlarmText.gameObject.SetAlpha((float)0.5);
public static void ClearChildren(this GameObject mbe) {
int childrenCount = mbe.gameObject.transform.childCount;
for (int i = childrenCount - 1; i >= 0; i--) {
UnityEngine.Object.Destroy(mbe.gameObject.transform.GetChild(i).gameObject);
}
}
if (obj) {
Canvas canvas = obj.AddComponent<Canvas> ();
canvas.overrideSorting = true;
canvas.sortingOrder = SORTING_ORDER_BYOND_POPUP_PAGES;
}
image.sprite = [your sprite]
C# code:
using UnityEngine;
using System ;
using System.Collections;
using System.Runtime.InteropServices;
public class PluginTools : MonoBehaviour {
#if UNITY_IPHONE || UNITY_XBOX360
[DllImport ("__Internal")]
#else
[DllImport ("BR_Plugin")]
#endif
private static extern void SetDebugFunction( IntPtr fp );
//[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void MyDelegate(string str);
[MonoPInvokeCallback(typeof(MyDelegate))]
static void CallBackFunction(string str)
{
Debug.Log(":: " + str);
}
public static void Init () {
MyDelegate callback_delegate = new MyDelegate( CallBackFunction );
IntPtr intptr_delegate =
Marshal.GetFunctionPointerForDelegate(callback_delegate);
SetDebugFunction( intptr_delegate );
}
}
c/c++ code
#include <string.h>
#include <stdio.h>
typedef void (*FuncPtr)( const char * );
FuncPtr _DebugFunc;
void SetDebugFunction(FuncPtr fp )
{
_DebugFunc = fp;
}
for using:
typedef void (*FuncPtr)( const char * );
extern FuncPtr _DebugFunc;
#define DebugLog( fmt, ... ) \
do { \
static char log_buf[1024] ; \
memset( log_buf , 0 , sizeof(log_buf)); \
sprintf(log_buf, fmt, ##__VA_ARGS__); \
_DebugFunc( log_buf ); \
} while (0)
bool bInvalidObj = gameObject == null || gameObject.Equals(null) || ReferenceEquals (gameObject, null);
- scroll content
- ScrollRect 组建中必须 设置 Content field, UGUI 创建的 scroll view 已自动设好
- cell item 需要添加到 content 上 , as child
- content 上一般需要添加
- Vertical/Horizontal Layout Group
- 设置 Child Force Expand
- Content Size Fitter ( 自动调整 content size )
- 设置成 Preferred Size
- Vertical/Horizontal Layout Group
- cell item
- 添加 Layout Element
scrollrect.content.anchoredPosition = Vector2.zero;
foreach(KeyValuePair<EventSignal,EventManager.EventFunc> entry in myRegisterEvents )
{
// to use entry.Key , entry.Value
}
- Microsoft's implementation of PKCS7 is a bit different than Python's
- python rkcs7
# encrypt
from Crypto.Cipher import AES
from Crypto import Random
from pkcs7 import PKCS7Encoder
iv = Random.new().read(AES.block_size)
aes = AES.new(aes_key, AES.MODE_CBC, iv )
base_encrypt = aes.encrypt(PKCS7Encoder().encode( d.encode( "utf8" ) ))
encrypt_d = base64.b64encode( iv + base_encrypt )
using System;
using System.IO;
using System.Security.Cryptography;
// c# decrypt
public String Decrypt_CBC_AES( string base64str, byte[] Key )
{
byte[] _entireText = System.Convert.FromBase64String (base64str);
byte[] IV = new byte[16];
Array.Copy ( _entireText , IV, 16 );
byte[] cipherText = new byte[ _entireText.Length - 16 ] ;
Array.Copy (_entireText, 16, cipherText, 0 , cipherText.Length );
_entireText = null;
// defaults to CBC and PKCS7
var aes = new AesManaged();
aes.Key = Key;
aes.IV = IV;
var decryptor = aes.CreateDecryptor();
var text_bytes = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length);
//var text = textEncoder.GetString(text_bytes);
return System.Text.UTF8Encoding.UTF8.GetString( text_bytes );
}
- do not use WWW , use WebClint instead
- set https / http proxy in you environment
HTTPS_proxy
,HTTP_proxy
- be aware of the upper/lower case
- start unity from
Unity.app/Contents/MacOS/Unity
, not by clicking Unity.app
Vector2 localpoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Input.mousePosition, GetComponentInParent<Canvas>().worldCamera, out localpoint);
Vector2 normalizedPoint = Rect.PointToNormalized(rectTransform.rect, localpoint);
Debug.Log(normalizedPoint);