在Unity中,Update()的方法是什么?以及如何制作自己的作品?

时间:2015-12-05 17:06:36

标签: c# unity3d monodevelop unity5

游戏对象如何知道虚拟更新意味着每一帧,而OnCollisionEnter意味着它们何时发生碰撞。我可以自己做吗?有点像这样

void OnPositionChange () {
 //code goes here
}

然后任何具有该OnPositionChange的脚本都会识别它并在位置发生变化时对其执行某些操作。

4 个答案:

答案 0 :(得分:2)

BuiltIn 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”用户的代码,正如一位评论员所说的那样)

答案 1 :(得分:0)

实际上你可以做到这一点。您只需创建自己的行为类。

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");
    }

}

这是你所说的我最接近的事情。

答案 2 :(得分:0)

          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.*/ }
            }

答案 3 :(得分:0)

Update()Start()以及具有此类特殊功能的其他方法来自overloadsMonoBehaviour。您可以看到所有脚本都派生自MonoBehaviour类。

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