【发布时间】:2016-03-10 13:30:41
【问题描述】:
游戏对象如何知道 void Update 是指每一帧,而 OnCollisionEnter 是指它们何时发生碰撞。我可以自己做吗?有点像
void OnPositionChange () {
//code goes here
}
然后任何具有该 OnPositionChange 的脚本都会识别它并在位置发生变化时对其进行处理。
【问题讨论】:
标签: c# unity3d monodevelop unity5
游戏对象如何知道 void Update 是指每一帧,而 OnCollisionEnter 是指它们何时发生碰撞。我可以自己做吗?有点像
void OnPositionChange () {
//code goes here
}
然后任何具有该 OnPositionChange 的脚本都会识别它并在位置发生变化时对其进行处理。
【问题讨论】:
标签: c# unity3d monodevelop unity5
内置 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 上的一个人问的)
【讨论】:
其实你可以做到。您可以简单地制作自己的 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");
}
}
这是最接近你问我相信的事情。
【讨论】:
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.*/ }
}
【讨论】:
Update()、Start() 和其他具有此类特殊功能的方法是来自MonoBehaviour 类的overloads。你可以看到你所有的脚本都是从MonoBehaviour类派生的。
您需要使用Events。您可以创建 event 和 delegate 以及在特殊情况下 raise 它们,以便在该事件中注册的所有脚本都可以为该事件调用自己的方法。
【讨论】: