zoukankan      html  css  js  c++  java
  • Unity脚本引用原理,修复Unity脚本引用丢失,源码脚本与dll中的脚本引用互换 .

    http://blog.csdn.net/gz_huangzl/article/details/52486509

    前言

    在我们开发游戏的过程中,经常会碰到脚本引用丢失的情况,但是怎么把它们修复到我们的理想情况呢?先在这打个预防针,不是所有情况下的脚本引用丢失都能修复,但绝大多数情况下都是可行的,只要你知道原来脚本的GUID和FILEID(不知道也可以在prefab中找到),最重要的是你要有(必须有)用来做修复的脚本GUID和FILEID,要不然就没办法修复 了。

    我举个极端情况,假如Prefab挂了A脚本,但是这个Prefab是第三方的,但是它却没有把A脚本给你,这种情况下你就没办法修复了,除非你通过其它途径知道了A脚本的实现,你自己在本地创建了一个类A的脚本,这样才可能被修复


    脚本在Prefab中被引用的原理

    脚本被引用有两种情况

    a.prefab引用的是cs文件脚本

    b.prefab引用的是dll文件中的脚本


    区别一:

    对于第一种情况,脚本的文件名必须和类名相同,且必须为MonoBehaviour类,不管脚本里面有一个或多个类,只有和文件名相同的类名的才能被挂接上

    对于第二种情况,一个脚本可以包含多个MonoBehaviour类,如果把它打成dll后,它里面的所有类都是可以被挂接

    区别二:

    prefab挂了脚本,打成AssetBundle后,加载运行的时候,只有第一种情况的脚本是可以生效的,挂的dll是无效,因为bundle加载并初始化的时候,unity是从包内的脚本中去搜索的,并不会从包内的dll中去搜索(这也是脚本更新的拦路虎之一,解决方法要么动态挂脚本,要么挂的脚本不热更,跟包走)


    引用的原理,如下图:


    用文本编辑器打开prefab文件,如上图,挂载的脚本如上紫框内所示,fileID脚本中类的信息,guild表示脚本所在的文件ID

    a.直接挂载脚本

        这种情况下,fileID的值永远是11500000,它实际上指的是MonoScript类型组件,它的值由ClassID * 10000所得,详情见官方文档,而guid能直接定位到MonoScript脚本文件

        所以它是通过guid找到脚本文件,然后挂载这个脚本中与脚本文件名相同的类

    b.直接挂载DLL中的脚本

       这种情况下,fileID的值是由"s" + type.Namespace + type.Name的值转换成MD4的值,guid指的是这个dll所对应的文件(MD4的算法贴在最后面)

       所以它是通过guid找到dll文件,然后生成里面所有类的MD4,然后和这个值做比对,相同的则挂载上去


    脚本引用修复

    一、原来是挂的脚本(可以通过fileID等于1150000判断),要替换成新的脚本

           a.把prefab中的guid通过文本工具统一替换成新脚本的guid

           b.直接把新脚本的.mate文件里面的guid改成prefab中的

           c.如果新脚本已经有地方有的,不能改.mate,就只能使用a方法

    二、原来是挂的DLL中的脚本(可以通过fileID不等于1150000判断),要替换成新的脚本

           a.把prefab中的guid改成新脚本的guid,把fileID统一改成1150000

    三、原来是挂的脚本,要替换成dll中的脚本

           a.把prefab中的guid改成dll的guid,把fileID统一改成DLL中类的Type算出来的MD4的值

    四、原来是挂的DLL中的脚本,要替换成新DLL中的脚本

           a.把prefab中的guid改成新dll的guid,把fileID统一改成新DLL中类的Type算出来的MD4的值


    注:如写工具时,要获得一个本地脚本中包含哪一些类,可以使用AssetDatabase.Load,它返回的是一个MonoScript,通过它可以获得到所有类的信息


    MD4算法如下:

    using System;using System.Collections.Generic;using System.Linq;using System.Security.Cryptography;namespace cn.crashByNull{    public class MD4 : HashAlgorithm    {        private uint _a;        private uint _b;        private uint _c;        private uint _d;        private uint[] _x;        private int _bytesProcessed;        public MD4()        {            _x = new uint[16];            Initialize();        }        public override void Initialize()        {            _a = 0x67452301;            _b = 0xefcdab89;            _c = 0x98badcfe;            _d = 0x10325476;            _bytesProcessed = 0;        }        protected override void HashCore(byte[] array, int offset, int length)        {            ProcessMessage(Bytes(array, offset, length));        }        protected override byte[] HashFinal()        {            try            {                ProcessMessage(Padding());                return new[] { _a, _b, _c, _d }.SelectMany(word => Bytes(word)).ToArray();            }            finally            {                Initialize();            }        }        private void ProcessMessage(IEnumerable<byte> bytes)        {            foreach (byte b in bytes)            {                int c = _bytesProcessed & 63;                int i = c >> 2;                int s = (c & 3) << 3;                _x[i] = (_x[i] & ~((uint)255 << s)) | ((uint)b << s);                if (c == 63)                {                    Process16WordBlock();                }                _bytesProcessed++;            }        }        private static IEnumerable<byte> Bytes(byte[] bytes, int offset, int length)        {            for (int i = offset; i < length; i++)            {                yield return bytes[i];            }        }        private IEnumerable<byte> Bytes(uint word)        {            yield return (byte)(word & 255);            yield return (byte)((word >> 8) & 255);            yield return (byte)((word >> 16) & 255);            yield return (byte)((word >> 24) & 255);        }        private IEnumerable<byte> Repeat(byte value, int count)        {            for (int i = 0; i < count; i++)            {                yield return value;            }        }        private IEnumerable<byte> Padding()        {            return Repeat(128, 1)               .Concat(Repeat(0, ((_bytesProcessed + 8) & 0x7fffffc0) + 55 - _bytesProcessed))               .Concat(Bytes((uint)_bytesProcessed << 3))               .Concat(Repeat(0, 4));        }        private void Process16WordBlock()        {            uint aa = _a;            uint bb = _b;            uint cc = _c;            uint dd = _d;            foreach (int k in new[] { 0, 4, 8, 12 })            {                aa = Round1Operation(aa, bb, cc, dd, _x[k], 3);                dd = Round1Operation(dd, aa, bb, cc, _x[k + 1], 7);                cc = Round1Operation(cc, dd, aa, bb, _x[k + 2], 11);                bb = Round1Operation(bb, cc, dd, aa, _x[k + 3], 19);            }            foreach (int k in new[] { 0, 1, 2, 3 })            {                aa = Round2Operation(aa, bb, cc, dd, _x[k], 3);                dd = Round2Operation(dd, aa, bb, cc, _x[k + 4], 5);                cc = Round2Operation(cc, dd, aa, bb, _x[k + 8], 9);                bb = Round2Operation(bb, cc, dd, aa, _x[k + 12], 13);            }            foreach (int k in new[] { 0, 2, 1, 3 })            {                aa = Round3Operation(aa, bb, cc, dd, _x[k], 3);                dd = Round3Operation(dd, aa, bb, cc, _x[k + 8], 9);                cc = Round3Operation(cc, dd, aa, bb, _x[k + 4], 11);                bb = Round3Operation(bb, cc, dd, aa, _x[k + 12], 15);            }            unchecked            {                _a += aa;                _b += bb;                _c += cc;                _d += dd;            }        }        private static uint ROL(uint value, int numberOfBits)        {            return (value << numberOfBits) | (value >> (32 - numberOfBits));        }        private static uint Round1Operation(uint a, uint b, uint c, uint d, uint xk, int s)        {            unchecked            {                return ROL(a + ((b & c) | (~b & d)) + xk, s);            }        }        private static uint Round2Operation(uint a, uint b, uint c, uint d, uint xk, int s)        {            unchecked            {                return ROL(a + ((b & c) | (b & d) | (c & d)) + xk + 0x5a827999, s);            }        }        private static uint Round3Operation(uint a, uint b, uint c, uint d, uint xk, int s)        {            unchecked            {                return ROL(a + (b ^ c ^ d) + xk + 0x6ed9eba1, s);            }        }    }    public static class FileIDUtil    {        public static int Compute(Type t)        {            string toBeHashed = "s" + t.Namespace + t.Name;            using (HashAlgorithm hash = new MD4())            {                byte[] hashed = hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(toBeHashed));                int result = 0;                for (int i = 3; i >= 0; --i)                {                    result <<= 8;                    result |= hashed[i];                }                return result;            }        }    }} 
    


     

  • 相关阅读:
    HDU 1010 Tempter of the Bone(DFS剪枝)
    HDU 1013 Digital Roots(九余数定理)
    HDU 2680 Choose the best route(反向建图最短路)
    HDU 1596 find the safest road(最短路)
    HDU 2072 单词数
    HDU 3790 最短路径问题 (dijkstra)
    HDU 1018 Big Number
    HDU 1042 N!
    NYOJ 117 求逆序数 (树状数组)
    20.QT文本文件读写
  • 原文地址:https://www.cnblogs.com/nafio/p/9137144.html
Copyright © 2011-2022 走看看