【问题标题】:In Unity, what type of method is Update()? And how to make my own?在 Unity 中,Update() 是什么类型的方法?以及如何制作我自己的?
【发布时间】:2016-03-10 13:30:41
【问题描述】:

游戏对象如何知道 void Update 是指每一帧,而 OnCollisionEnter 是指它们何时发生碰撞。我可以自己做吗?有点像

void OnPositionChange () {
 //code goes here
}

然后任何具有该 OnPositionChange 的脚本都会识别它并在位置发生变化时对其进行处理。

【问题讨论】:

    标签: c# unity3d monodevelop unity5


    【解决方案1】:

    内置 SendMessage 组件: http://docs.unity3d.com/ScriptReference/Component.SendMessage.html

    我猜这可能会对您有所帮助: http://answers.unity3d.com/questions/676625/creating-my-own-custom-unity-messages.html

    这里的建议是创建一个基类,所有需要该方法的对象都从该基类扩展。在示例中,他使用了损坏源和可损坏对象,并举例说明了它们如何交互:

    在 DamageSource.cs(你用来对 造成伤害的类)

    using UnityEngine;
     using System.Collections;
    
     public class DamageSource : MonoBehaviour {
         protected float damageAmount = 10f;
    
         //not 100% necessary, but handy for an example of how to 
         //handle damage based on the attacker (which is 
         //relevant for info sent in the OnTakeDamage() method
         protected ElementType elementType = ElementType.Normal;
    
         //we use a function for getting the damage this 
         //DamageSource can do because it lets us overwrite it.
         //Eg, if the enemy is weakened, you can factor that 
         //in and return a lesser amount of damage.
         public float GetDamageAmount() {
             return damageAmount;
         }
    
         public ElementType GetElementType() {
             return elementType;
         }
     }
    
     //kinds of elements available for damage / resistance calculations
     public enum ElementType {
         Normal,
         Fire,
         Ice,
         Lightning
     }
    

    在 DamageableObject.cs(所有可损坏对象继承的基类)中:

    using UnityEngine;
     using System.Collections;
    
     public class DamageableObject : MonoBehaviour {
         protected bool wasRecentlyHit;
         protected float health;
         protected float maxHealth;
    
         public void Awake() {
             health = maxHealth;
         }
    
         //Creating a virtual void method lets you choose whether 
         //or not you want to set it in a derived class.
         //Here, we track the amount of damage and the source 
         //the damage came from. This can sometimes be handy for 
         //context-sensitive reactions to being damaged. Eg, play 
         //a particular sound in damaging the player, when 
         //successfully damaged by a particular attack.
         //Note that this base implementation does nothing - you 
         //override it in an inheriting class, very similar to using Update() etc.
         protected virtual void OnTakeDamage(float damageAmount, DamageSource damageSource) {}
         //An example of how you'd check whether damage is incoming. 
         //You can alternatively just call 
         //someDamageableObject.TryDoDamage() from another script.
         public void OnTriggerEnter(Collider other) {
             DamageSource damageGiver = other.GetComponent<DamageSource>();
             if (damageGiver) {
                 TryDoDamage(damageGiver.GetDamageAmount(),damageGiver.gameObject);
             }
         }
         public void TryDoDamage(float damageAmount, GameObject damageGiver) {
             //early out, this DamageableObject was damaged a very 
             //short time ago and shouldn't be damaged again so soon
             if (wasRecentlyHit) return;
    
             //optionally perform any damage calculations here based
             //on the damageGiver, eg more damage from the player 
             //being weakened somehow, or less damage from type 
             //resistances... etc.
             damageAmount = CalculateDamage(damageAmount,damageGiver);
    
             //if after our damage calculations we still have an 
             //amount of damage greater than 0, we do the damage and 
             //send the OnTakeDamage() message.
             if (damageAmount>0f) {
                 health -= damageAmount;
    
                 //optional handling of dying (uncomment this and the OnDeath() function to enable)
                 //if (health<0f) {
                 //    OnDeath(damageAmount,damageGiver);
                 //}
                 //else {
                 OnTakeDamage(damageAmount,damageGiver);
                 //}
             }
         }
    
         //Uncomment this and the (healtn<0f) if statement above 
         //if you want to handle dying as well as being damaged
         //protected virtual void OnDeath(float damageAmount, DamageSource damageSource);
    
         //Default implementation for calculating damage, 
         //given some amount of damage, and some source of damage.
         //Override this in an inheriting class if you want to do 
         //different damage, eg based on the damage source (2x 
         //damage from fire attacks, 0.5x damage from ice 
         //attacks... etc) or based on the DamageableObject's 
         //current state (eg, player is weakened, so takes 1.5x damage)
         protected float CalculateDamage(float damageAmount, DamageSource damageSource) {
             return damageAmount;
         }
     }
    

    在 PlayerDamageReceiver.cs 中:

    using UnityEngine;
     using System.Collections;
    
     public class PlayerDamageReceiver : DamageableObject {
    
         //override the OnTakeDamage() method to make a 
         //different implementation of it for this class
         protected override void OnTakeDamage(float damageAmount, DamageSource damageSource) {
             Debug.Log("Ouch, the player was damaged!");
         }
    
         //Uncomment this to override the OnDeath() function 
         //in DamageableObject (if you've uncommented that, that is)
         //protected override void OnDeath(float damageAmount, DamageSource damageSource) {
         //    Debug.Log("Uhoh... The player died. :(");
         //}
    
         //override the CalculateDamage() function to 
         //determine how damage applies to the player
         protected override float CalculateDamage(float damageAmount, DamageSource damageSource) {
             //Example: give the player a 2x weakness to fire damage, and immunity to ice damage
             switch (damageSource.GetElementType()) {
                 case (ElementType.Fire):
                     damageAmount *= 2f;
                     break;
                 case (ElementType.Ice):
                     damageAmount = 0f;
                     break;
             }
             return damageAmount;
         }
     }
    

    (我从“nesis”用户那里复制并粘贴了代码,这是 cmets 上的一个人问的)

    【讨论】:

    • 对于后代,您能否在您的答案中包含您认为有用的链接的相关部分?这样,如果链接断开、更改等,您的答案不会变得无用。非常感谢。
    【解决方案2】:

    其实你可以做到。您可以简单地制作自己的 Behavior 类。

    public class MyBehavior : MonoBehaviour {
    
        Vector3 lastPosition = new Vector3();
    
        void Update () {
            Vector3 position = new Vector3();
            if (position != lastPosition)
            {
                OnPositionChange();
                lastPosition = position;
            }
            else
            {
                lastPosition = position;
            }
        }
    
        public virtual void OnPositionChange(){}
    }
    

    现在你定义你的脚本,它直接继承 MyBehavior 而不是 MonoBehavior。

    public class test : MyBehavior {
    
        public override void OnPositionChange()
        {
            Debug.Log("override");
        }
    
    }
    

    这是最接近你问我相信的事情。

    【讨论】:

      【解决方案3】:
                float startPositionX;
                float startPositionY;
                float startPositionZ;
                float currentPositionX;
                float currentPositionY;
                float currentPositionZ;
      
      
                  void start(){
                  startPositionX = gameObject.transform.position.x ;
                  startPositionY = gameObject.transform.position.y ;
                  startPositionz = gameObject.transform.position.z ;
                   }
      
                  void update() {
                  currentPositionX = gameObject.transform.position.x ;
                  currentPositionY = gameObject.transform.position.y ;
                  currentPositionZ = gameObject.transform.position.z ;
                  OnPositionChange ();
                  }
      
      
               void OnPositionChange () {
               if(startPositionX == ! currentPositionX ||
                  startPositionY == ! currentPositionY || 
                  startPositionZ == ! currentPositionZ){
                  /*write your own code that you want to perform.*/ }
                  }
      

      【讨论】:

        【解决方案4】:

        Update()、Start() 和其他具有此类特殊功能的方法是来自MonoBehaviour 类的overloads。你可以看到你所有的脚本都是从MonoBehaviour类派生的。

        您需要使用Events。您可以创建 event 和 delegate 以及在特殊情况下 raise 它们,以便在该事件中注册的所有脚本都可以为该事件调用自己的方法。

        【讨论】:

          猜你喜欢
          • 2018-06-25
          • 2013-12-21
          • 2023-01-26
          • 2014-11-15
          • 1970-01-01
          • 2011-01-09
          • 2015-07-19
          • 2020-09-17
          相关资源
          最近更新 更多