从 Update 方法中移出比较:使用委托代替还是其他方法?
Moving comparisons out from the Update method: using delegates instead or another approach?
我们直接上例子。假设我们有:
Update(){
if (value.Equals("circular")) moveGameObjectInACircularWay();
else if (value.Equals("linear")) moveGameObjectInALinearWay();
}
我认为这不是很优雅的解决方案。 Unity需要每一帧都进行一次比较。这对我来说听起来不是很理想。我只是猜测它应该是其他实现方式,例如:
Start () {
if (value.Equals("circular")) movement += moveGameObjectInACircularWay;
else if (value.Equals("linear")) movement += moveGameObjectInALinearWay;
}
Update () {
movement();
}
我想解决方案与代表有关。这就是为什么我提出的解决方案看起来像代表。我还不明白什么代表还好。
来自 MSDN "C# 中的委托类似于 C 或 C++ 中的函数指针。使用委托允许程序员将对方法的引用封装在委托对象中。" (https://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx) 简而言之就是一个指向方法的指针。您要做的是:
using UnityEngine;
using System.Collections;
public delegate void MovementDelegate();
public class Movement : MonoBehaviour {
MovementDelegate movementFunction=null;
public string value = "linear";
void Start () {
if (value.Equals("circular")) movementFunction = moveGameObjectInACircularWay;
else if (value.Equals("linear")) movementFunction = moveGameObjectInALinearWay;
}
// Update is called once per frame
void Update()
{
if (movementFunction != null)
{
movementFunction();
}
}
void moveGameObjectInACircularWay()
{
Debug.Log("do circular movement here");
}
void moveGameObjectInALinearWay()
{
Debug.Log("do linear movement here");
}
}
您声明的函数必须与委托签名具有相同的签名。如果你想给它添加参数,例如。一个 int,将你的委托标记为
public delegate void MovementDelegate(int speed);
并且您的实现功能为
void moveGameObjectInACircularWay(int speed)
void moveGameObjectInALinearWay(int speed)
并将调用更改为
movementFunction(yourIntHere)
已更新!:感谢 Joe Blow 的建议,这是另一个解决方案:
public class Movement : MonoBehaviour
{
Action<int> movementFunction = null;
public string value = "linear";
void Start()
{
if (value.Equals("circular")) movementFunction = moveGameObjectInACircularWay;
else if (value.Equals("linear")) movementFunction = moveGameObjectInALinearWay;
}
// Update is called once per frame
void Update()
{
if (movementFunction != null)
{
movementFunction(2);
}
}
void moveGameObjectInACircularWay(int speed)
{
Debug.Log("do circular movement here "+ speed);
}
void moveGameObjectInALinearWay(int speed)
{
Debug.Log("do linear movement here " + speed);
}
}
我最喜欢的答案是 Joe Blow 在评论中写的:
Unity 是基于组件的。我们最好 switch to Component-Based Thinking 而不是与代表一起工作。
所以制作两个(或更多)不同的脚本,并将它们放在有问题的游戏对象上。然后,根据需要打开和关闭这些组件。
因此我们必须将脚本添加到我们的游戏对象中:MoveGameObjectInACircularWay.cs 和 MoveGameObjectInALinearWay.cs。然后一个MainGameObjectScript.cs也添加到我们的游戏对象中,代码如下:
void Start () {
GetComponent()<MoveGameObjectInACircularWay>.active = true;
GetComponent()<MoveGameObjectInALinearWay>.active = false;
}
我们直接上例子。假设我们有:
Update(){
if (value.Equals("circular")) moveGameObjectInACircularWay();
else if (value.Equals("linear")) moveGameObjectInALinearWay();
}
我认为这不是很优雅的解决方案。 Unity需要每一帧都进行一次比较。这对我来说听起来不是很理想。我只是猜测它应该是其他实现方式,例如:
Start () {
if (value.Equals("circular")) movement += moveGameObjectInACircularWay;
else if (value.Equals("linear")) movement += moveGameObjectInALinearWay;
}
Update () {
movement();
}
我想解决方案与代表有关。这就是为什么我提出的解决方案看起来像代表。我还不明白什么代表还好。
来自 MSDN "C# 中的委托类似于 C 或 C++ 中的函数指针。使用委托允许程序员将对方法的引用封装在委托对象中。" (https://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx) 简而言之就是一个指向方法的指针。您要做的是:
using UnityEngine;
using System.Collections;
public delegate void MovementDelegate();
public class Movement : MonoBehaviour {
MovementDelegate movementFunction=null;
public string value = "linear";
void Start () {
if (value.Equals("circular")) movementFunction = moveGameObjectInACircularWay;
else if (value.Equals("linear")) movementFunction = moveGameObjectInALinearWay;
}
// Update is called once per frame
void Update()
{
if (movementFunction != null)
{
movementFunction();
}
}
void moveGameObjectInACircularWay()
{
Debug.Log("do circular movement here");
}
void moveGameObjectInALinearWay()
{
Debug.Log("do linear movement here");
}
}
您声明的函数必须与委托签名具有相同的签名。如果你想给它添加参数,例如。一个 int,将你的委托标记为
public delegate void MovementDelegate(int speed);
并且您的实现功能为
void moveGameObjectInACircularWay(int speed)
void moveGameObjectInALinearWay(int speed)
并将调用更改为
movementFunction(yourIntHere)
已更新!:感谢 Joe Blow 的建议,这是另一个解决方案:
public class Movement : MonoBehaviour
{
Action<int> movementFunction = null;
public string value = "linear";
void Start()
{
if (value.Equals("circular")) movementFunction = moveGameObjectInACircularWay;
else if (value.Equals("linear")) movementFunction = moveGameObjectInALinearWay;
}
// Update is called once per frame
void Update()
{
if (movementFunction != null)
{
movementFunction(2);
}
}
void moveGameObjectInACircularWay(int speed)
{
Debug.Log("do circular movement here "+ speed);
}
void moveGameObjectInALinearWay(int speed)
{
Debug.Log("do linear movement here " + speed);
}
}
我最喜欢的答案是 Joe Blow 在评论中写的:
Unity 是基于组件的。我们最好 switch to Component-Based Thinking 而不是与代表一起工作。
所以制作两个(或更多)不同的脚本,并将它们放在有问题的游戏对象上。然后,根据需要打开和关闭这些组件。
因此我们必须将脚本添加到我们的游戏对象中:MoveGameObjectInACircularWay.cs 和 MoveGameObjectInALinearWay.cs。然后一个MainGameObjectScript.cs也添加到我们的游戏对象中,代码如下:
void Start () {
GetComponent()<MoveGameObjectInACircularWay>.active = true;
GetComponent()<MoveGameObjectInALinearWay>.active = false;
}