游戏对象如何知道虚拟更新意味着每一帧,而OnCollisionEnter意味着它们何时发生碰撞。我可以自己做吗?有点像这样
void OnPositionChange () {
//code goes here
}
然后任何具有该OnPositionChange的脚本都会识别它并在位置发生变化时对其执行某些操作。
答案 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()
以及具有此类特殊功能的其他方法来自overloads
类MonoBehaviour
。您可以看到所有脚本都派生自MonoBehaviour
类。
您需要使用Events
。您可以创建event
和delegate
以及特殊情况raise
,以便在该事件中注册的所有脚本都可以为该事件调用自己的方法。