精华内容
下载资源
问答
  • http://docs.unity3d.com/ScriptReference/MonoBehaviour.html   脚本除了代码本身的功能以外,当然还有一个最重要的功能:序列化。Unity中,脚本对象是由引擎帮忙创建的。 Unity 保存一个场景或者一个预设时...

    Unity 是基于组件式的开发,gameObject 身上可以绑定任意个脚本。每个脚本组成 gameObject 的一个部分。

    脚本里通过添加预定义好的函数来执行自己的任务。比如Awake,用于初始化,Update用于每帧更新,还有一些跟事件相关的函数。

    这些预定义的函数是由 Unity 引擎在适当的时刻自动调用的。

    预定义函数的完整列表可以查看 Unity 文档:

    http://docs.unity3d.com/ScriptReference/MonoBehaviour.html

     

    脚本除了代码本身的功能以外,当然还有一个最重要的功能:序列化。Unity中,脚本对象是由引擎帮忙创建的。

    Unity 保存一个场景或者一个预设时,对每个 gameObject 对象存储着序列化数据,这些数据在脚本对象被创建时,会被正确地设置到脚本的字段上。

    ....序列化并不能支持所有的数据类型。

     

    ..........未完待续,现在是 2015年7月23号,23:55

    转载于:https://www.cnblogs.com/answerwinner/p/4672134.html

    展开全文
  • ...void MonoBehaviour::TransferEngineAndInstance (TransferFunction& transfer) { PPtr<MonoScript> newScript = TransferEngineData (transfer); if (transfer.IsReadingPPtr ())

    在MonoBehaviour.cpp中有这样一个Rebuild方法,它主要执行了CreateMonoScriptCache这样一个方法。

     

    void MonoScript::Rebuild (ScriptingTypePtr klass)
    {
    	......
    	
    	m_ScriptCache = CreateMonoScriptCache (klass, m_IsEditorScript, this);
    }

    在CreateMonoScriptCache方法中,我们主要关注BuildMethodCache 和PopulateMethods方法。

    MonoScriptCache* CreateMonoScriptCache (ScriptingTypePtr klass, bool isEditorScript, Object* errorContext)
    {
    	......
    
    	
    	BuildMethodCache (cache->methodCache, cache->klass, false);
    
        PopulateMethods(*cache, cache->klass, errorContext);
    
        ......
    	
    	return cache;
    }

    在BuildMethodCache方法中,通过调用

    GetScriptingMethodRegistry().AllMethodsIn(klass, foundMethods, ScriptingMethodRegistry::kInstanceOnly);

    将需要查找的方法放入到foundMethods这样的vector<ScriptingMethodPtr>列表中。

    然后遍历这个列表,将<方法名,ScriptingMethodPtr 方法调用指针>插入到MethodCache&类型的 methods中。

    static void BuildMethodCache (MethodCache& methods, ScriptingClassPtr klass, bool staticMethod)
    {
    	AssertIf (klass == NULL);
    	
    	std::vector<ScriptingMethodPtr> foundMethods;
    	GetScriptingMethodRegistry().AllMethodsIn(klass, foundMethods, ScriptingMethodRegistry::kInstanceOnly);
    	
    	for (std::vector<ScriptingMethodPtr>::iterator methodIterator = foundMethods.begin(); methodIterator != foundMethods.end(); methodIterator++)
    	{
    		ScriptingMethodPtr method = *methodIterator;
    		
    		std::string curName = scripting_method_get_name (method);
    		if (methods.find (curName.c_str()) != methods.end ())
    			continue;
    		
    		methods.insert (std::make_pair (strcpy (new char[curName.length() + 1], curName.c_str()), method));
    	}
    }

     注意关注到MonoScriptCache中的一个枚举

    enum { kUpdate = 0, kLateUpdate, kFixedUpdate, kAwake, kStart, kMain, kRenderObject, kAddToManager, kRemoveFromManager, kRemoveFromManagerInternal, kCoroutineStart, kCoroutineMain, kRenderImageFilter, kDrawGizmos, kGUI, kValidateProperties, kSerializeNetView, kNetworkInstantiate, kOnDestroy, kAudioFilterRead, kMethodCount };
    	

    在PopulateMethods方法中,通过遍历枚举kMethodCount次,根据方法名kMethodNames数组拿到方法名,通过调用FindMethod方法,传入方法名,查找到对应的ScriptingMethodPtr这样类型的方法指针,进而建立起了从前文中的<方法名,ScriptingMethodPtr 方法调用指针>到<下标索引,ScriptingMethodPtr 方法调用指针>。

    static void PopulateMethods(MonoScriptCache& cache, MonoClass* klass, Object* errorContext)
    {
    	......
    
    	for (int i=0;i<MonoScriptCache::kMethodCount;i++)
    	{
    		DebugAssertIf(kMethodNames[i] == NULL);
    		
    		ScriptingMethodPtr method = FindMethod (cache, kMethodNames[i]);
            
            ......
            
    		cache.methods[i] = method;
    	}
    	
        ......
    	
    }

    当我们在调用Awake方法时,主要是在CallMethodIfAvailable 中传入方法的索引,获取到ScriptingMethodPtr这样一个方法指针,进而完成对它的调用。

    void MonoBehaviour::SetupAwake ()
    {
    	if (IsPlayingOrAllowExecuteInEditMode () && !m_DidAwake && GetInstance() && IsActive ())
    	{
    		m_DidAwake = true;
    		CallMethodIfAvailable (MonoScriptCache::kAwake);
    	}
    }
    
    inline void MonoBehaviour::CallMethodIfAvailable (int methodIndex)
    {
    	AssertIf (methodIndex < 0 || methodIndex >= MonoScriptCache::kMethodCount);
    	ScriptingMethodPtr method = m_Methods[methodIndex];
    	if (method == SCRIPTING_NULL)
    	{
    		return;
    	}
    
    	AssertIf (GetInstance() == SCRIPTING_NULL);
    	AssertIf (!m_DidAwake);
    
    	if (!IsActive ())
    		return;
    	
    	ScriptingInvocationNoArgs invocation(method);
    	invocation.objectInstanceIDContextForException = GetInstanceID();
    	invocation.object = GetInstance();
    	invocation.Invoke();
    }

    同理可得Start方法

    inline void MonoBehaviour::Start ()
    {
    	......
    	
    	m_DidStart = true;
    	
    	ScriptingMethodPtr method;
    	method = m_Methods[MonoScriptCache::kCoroutineMain];
    	
    	if (method)
    		InvokeMethodOrCoroutineChecked (method, SCRIPTING_NULL);
    	
    	method = m_Methods[MonoScriptCache::kCoroutineStart];
    	if (method)
    		InvokeMethodOrCoroutineChecked (method, SCRIPTING_NULL);
    }

    注意到几个Update方法

    void MonoBehaviour::Update ()
    {
    	CallUpdateMethod (MonoScriptCache::kUpdate);
    }
    
    void MonoBehaviour::LateUpdate ()
    {
    	CallUpdateMethod (MonoScriptCache::kLateUpdate);
    }
    
    void MonoBehaviour::FixedUpdate ()
    {
    	CallUpdateMethod (MonoScriptCache::kFixedUpdate);
    }
    void MonoBehaviour::CallUpdateMethod(int methodIndex)
    {
    	AssertIf (!IsPlayingOrAllowExecuteInEditMode ());
    	AssertIf (!IsActive ());
    	AssertIf (!GetEnabled ());
    	ScriptingObjectPtr instance = GetInstance();
    	
    	if (instance == SCRIPTING_NULL)
    		return;
    	// Ensure Start has been called
    	Start ();
    	
    	// We might be getting destroyed in Start
    	if (!IsInstanceValid(instance))
    		return;
    
    	// Call Update
    	CallMethodIfAvailable (methodIndex);
    }
    

    而至于Unity的引擎层如何和高级语言脚本类关联上,主要是通过Mono运行时嵌入到应用中,提供这样的脚本运行机制。

    展开全文
  • Unity的MonoBehaviour详解

    千次阅读 2019-03-01 21:07:06
    这个答案明显是错误的,所以今天有时间就好好查看一下资料这个东西的被调用的原理是什么? 先观察一下MonoBehaviour的继承关系 Object-&gt;Component-&gt;Behaviour-&gt;MonoBeha...

    前言:

    之前面试被问到生命周期函数是怎么被调用起来的?,当时我只知道生命周期函数的调用顺序,但是完全不知道它是如何被调用起来,只能尴尬的回答是函数的重写吗?这个答案明显是错误的,所以今天有时间就好好查看一下资料这个东西的被调用的原理是什么?

    1. 先观察一下MonoBehaviour的继承关系

    Object->Component->Behaviour->MonoBehaviour在这些类中确实没有发现生命周期函数名。本以为应该在MonoBehaviour中设计一个abstract或virtual的生命周期的方法,然后让子类去重写这些方法,但是发现父类根本没有定义这些生命周期函数。

         2.网上查阅资料,查看可能原因

    经过一些资料的阅读惊讶的发现,MonoBehaviour的声明周期函数竟然是通过发射了调用的,这样设计出于什么目?有什么好处?这是值得思考的一个问题。Unity使用类反射而非虚函数的方式来调用Update等函数,主要原因是在于,并非所有的MonoBehaviour都需要Update(或Start,Awake等等,下同)。Unity会维护一个需要Update的Behaviour列表,藉此避免进行空的虚函数调用,提高性能,反射也可以访问私有方法。

    • mono的API来实现的(而不是C#内建的反射机制),没看过Unity的源码所以不敢做定论,但我的理解是,mono的这套机制也是reflection,只不过不是The Reflection而已,不需要太教条地去理解。Mono的API可能效率更高,但对于单次调用,性能仍然逊于虚方法调用。
    • 反射实际上是开销非常大的调用方式,比之虚方法来说要高得多,因此Unity选择使用反射并非是出于性能方面的考虑。实际上,每帧调用的这些事件方法从数量级上来说是很卑微的,反射造成的性能影响亦可忽略不计;
    • Unity使用这种事件机制的根本原因是出于对灵活性的考虑。Unity采用组件式设计,触发一个事件,需要通知到相应gameobject的所有组件。如果使用多态来实现,则必须假设所有组件都派生自包含此事件的基类,或者筛选出派生自此基类的组件逐一通知。这样一来是麻烦,二来则容易带来复杂的继承关系,与组件式这种倡导用聚合代替继承的设计从理念上就是相悖的。
    • 这种设计最大的缺陷在于事件名通过字符串耦合,如此一来,完全绕开了编译期静态检查,无法为事件调用的正确性提供保障;在复杂的系统里,也可能因为事件重名而导致bug。

         3.反射调用的简单代码

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;
    using UnityEngine;
    
    public class InvokeReflection : MonoBehaviour
    {
        void Start()
        {
            demo();
        }
    
    
        public void demo()
        {
            /*
             *System.Reflection.Assembly类有两个静态方法:Assembly.Load(string assemblyname)和Assembly.LoadFrom(string filename) 。
             * 通常用这两个方法把程序集加载到应用程序域中。 如果你希望加载的程序集超出了CLR的预定探查范围,你可以用 Assembly.LoadFrom直接从一个文件位置加载程序集。
             * Assembly.LoadFrom()和Assembly.LoadFile(),两者的主要区别有两点:
             * 一:Assembly.LoadFile()只载入指定的dll文件,而不会自动加载相关的dll文件。如果下文例子使用Assembly.LoadFile()加载SayHello.dll,那么程序就只会加载
             * SayHello.dll而不会去加载SayHello.dll引用的BaseClass.dll文件。
             *二:用Assembly.LoadFrom()载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly;
             * 而Assembly.LoadFile()则不会做类似的检查。
             */
            //C:\Users\Administrator\Desktop\New Unity Project\Assets\DLL
            Assembly assemly2 = Assembly.LoadFrom(@"E:\Desktop\Project_Data\UnityPro\Practice_Item\TextPro\Assets\Scripts\TestReflection.dll");
            Assembly assemly1 = Assembly.LoadFile(@"E:\Desktop\Project_Data\UnityPro\Practice_Item\TextPro\Assets\Scripts\TestReflection.dll");
            Assembly assemly = Assembly.Load("TestReflection");//1填加DLL
            Type testType = assemly.GetType("HaiLan.TestReflection.TestReflectionDLL");//2获取对应的类信息,需要填加对应的命名空间
            object oTestReflectionDLL = Activator.CreateInstance(testType);//3 创建对象
            IReflectionDLL iTestReflectionDLL = oTestReflectionDLL as IReflectionDLL;//4 类型转换
            iTestReflectionDLL.TestShow1();//5 方法调用
    
            foreach (var item in assemly.GetModules())
            {
                Debug.Log(item.Name);//打印结果 TestReflection.dll
            }
            foreach (var type in assemly.GetTypes())
            {
                Debug.Log(type.Name);
                foreach (var item in type.GetMethods())
                {
                    Debug.Log(item.Name);
                }
            }
        }
    
    }

     

    展开全文
  • MonoBehaviour的UI框架

    千次阅读 2017-02-18 23:22:14
    相关的知识请点击:http://www.blogjava.net/Jack2007/archive/2008/05/05/198566.html原理什么的就不一一详谈了,直接上代码了:using UnityEngine; using System.Collections; using UnityEngine.UI; public ...

    相关的知识请点击:

    http://www.blogjava.net/Jack2007/archive/2008/05/05/198566.html


    原理什么的就不一一详谈了,直接上代码了:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    public abstract class BaseView
    {
        public GameObject myGameObject;
        public void Setup(Transform root)
        {
            myGameObject = root.gameObject;
            Init();
        }
    
        protected virtual void Init()
        { 
        }
    }
    
    public class ViewTest : BaseView
    {
        public Text txt;
        public Button btn;
        public Text btnText;
    
        protected override void Init()
        {
            base.Init();
            Transform root = this.myGameObject.transform;
            txt = root.Find("Text").GetComponent<Text>();
            btn = root.Find("Button").GetComponent<Button>();
            btnText = root.Find("Button/Text").GetComponent<Text>();
        }
    }
    
    

    using UnityEngine;
    using System.Collections;
    
    public class MonoViewController<T> : MonoBehaviour where T : BaseView, new()
    {
        private T _view;
    
        protected T View
        {
            get
            {
                if (_view == null)
                {
                    _view = new T();
                    _view.Setup(gameObject.transform);
                }
                return _view;
            }
        }
    }
    


    using UnityEngine;
    using System.Collections;
    
    public class TestController : MonoViewController<ViewTest> {
    
        void Start()
        {
    
            View.btn.onClick.AddListener(OnClick);
        }
    
        public void OnClick()
        {
            View.txt.text = "欢迎关注本人博客";
            View.btnText.text = "关注吧!!!";
        }
    }
    


    效果图:

                           



    展开全文
  • MonoBehaviour 编写C#

    千次阅读 2013-05-14 17:29:44
    切记:  float test; 进行除法运算的时候要注意:  test = 8 / 10; Debug.log(" test is ---> "+ test);  =====> test is 0; 改:  test = 8 .0f / 10.0f; Debug.log(" test is ---> "+ test);
  • 本篇文章将详细讲解MonoBehaviour中的帧更新函数。 相信只要是在Unity中写过代码的人都知道Monobehaviour这个类。当你的脚本去继承这个Monobehaviour类并挂在在场景中的游戏物体上,那么当游戏运行时,则会执行这个...
  • 首先要明确的是MonoBehaviour是每个脚本的基类.每个Javascript脚本自动继承MonoBehaviour.使用C#或Boo时,需要显式继承MonoBehaviour. Unity是不支持多线程的,也就是说我们必须要在主线程中操作它,...
  • 《UnityAPI.MonoBehaviour行为》 版本 作者 参与者 完成日期 备注 UnityAPI_MonoBehaviour_V01_1.0 严立钻 2020....
  • 【Java】Iterator底层原理,自己实现Iteratorpackage test;import java.util.Iterator;public class MyIterator implements java.lang.Iterable {private String[] element = {"a","b","c","d","e"};private int s.....
  • Unity与注册登录服务器交互原理及codePosted on 2013年07月07日 by U3d / \o "查看 Unity3D 基础教程 中的全部文章" Unity3D 基础教程/被围观 70 次主要用到了unity内置的WWW类和WWWForm类,运用WWWForm.AddField...
  • Unity Avatar换装原理实例

    万次阅读 2017-05-13 17:53:52
    本文向大家介绍Unity换装原理及其简单实现 首先附上效果图: 本文的源码我将上传提供大家下载 实现原理:控制角色SkinMeshRenderer组件的mesh、materials、bones属性来实现角色换装 在该Demo素材中,主角是由多个...
  • 网上关于自制UIMask的博客也不少了 丢掉Mask遮罩,更好的圆形Image组件[Unity] 这里在自学了一部分之后详细记录一下 圆形遮罩的原理 以及 在自制mask里面实现精确点击的原理 以及 部分的编辑器知识 目前的UGUI有mask...
  • Unity协程(Coroutine)原理深入剖析

    千次阅读 2016-04-09 12:25:16
    Unity协程(Coroutine)原理深入剖析    By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com    记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程...
  • 总结角色换装原理

    2016-02-20 19:41:00
    总结角色换装原理 http://unity.jb51.net/xuexipeixun/rumenjiaocheng/1461.html 在换装前,我先讲讲WWW的相关事宜。 c#里用WWW去读取资源时,需要用到迭代器IEnumerator和 ...
  • Unity3D消消乐实现原理

    千次阅读 2017-07-16 17:42:16
    基本原理:  遍历所有宝石集合,判断行和列三连的情况,删除三连,更新上方宝石位置. 1.定义一个宝石脚本,功能:随机指定宝石类型,指定宝石位置,iTween动画,销毁,颜色 using UnityEngine; using System.Collections; ...
  • 这个系列文章,是为了记录分析UGUI的各种原理: UGUI的渲染模式。 UGUI的缩放计算。 UGUI的锚点定位。 UGUI的层级渲染流程。 UGUI的事件触发原理。 UGUI的布局自动布局方式。 这是本系列文章的第X篇: 二、如何...
  • 射线原理

    2017-08-21 20:55:38
    在3D游戏中,呈现给玩家的始终是一个2D的平面...首先究竟什么是射线原理,顾名思义,在射线原理中存在一条射线来定义鼠标映射在3D世界中的点。以摄像机为射线发出的原点,以鼠标的位置为目标点,在这两点之间发射一条射
  • 说明:类名与脚本组件名一致,并自动的继承MonoBehaviour类;( 类名与脚本名不一样会出错 )           ##3.2、Unity脚本组件 ##3.2、Unity脚本组件 ++3.2、Unity脚本组件...
  • 所以若要访问Unity中的组件,我们可以去用协程,和线程差不多,但是原理有本质上的不同: 协程仍然是在主线程中去执行的。协程不是线程,也不是异步执行的。协程和 MonoBehaviour 的 Update函数一样也是在Main...
  • 换装原理实践

    2018-12-17 19:53:20
    换装原理初探 换装原理中篇 效果图 UI制作 Toggle组,区分性别。 对于每种性别,Toggle组,区分部位。 对于每个部位,Toggle组,区分型号。 性别切换时,触发两个函数,UI上性别Toggle组切换,AvatarCustomization...
  • @[TOC]unity物理射线之原理分析(擅码网学习笔记) using System.Collections; using System.Collections.Generic; using UnityEngine; ///<summary> /// ///</summary> public class RayTest : ...
  • Unity/UGUI底层绘制原理

    2019-09-11 09:50:59
    UnityDraw.cs using System.Collections; using System.Collections.Generic; using UnityEngine;...public class UnityDraw : MonoBehaviour { public Texture2D TestTexture;//测试用贴图 void Start() { ...
  • untiy 协程原理分析

    2014-12-31 16:44:26
    协程和 MonoBehaviour 的 Update函数一样也是在MainThread中执行的。使用协程你不用考虑同步和锁的问题。 UnityGems.com给出了协程的定义: A coroutine is a function that is executed partially and, ...
  • 贝塞尔曲线是一种绘制曲线的方法,它的原理很简单: 以二阶贝塞尔曲线为例 如图,在p0,p1之间移动着一个点,我们先称之为a0,同样在p1,p2之间移动着一个点,我们称之为a1。他们需要满足的条件是这样的,在移动中,...
  • xlua原理解析

    2020-12-22 14:38:27
    本文通过对XLua的HoxFix使用原理的研究揭示出来这样的一套方法。这个方法的第一步:通过对C#的类与函数设置Hotfix标签。来标识需要支持热更的类和函数。第二步:生成函数连接器来连接LUA脚本与C#函数。第三步:在C#...
  • 先来直接放一段代码 1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine;... 5 public class CoroutineTest : MonoBehaviour 6 { 7 8 void Start() 9 { ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,631
精华内容 1,852
关键字:

monobehaviour原理