如何从 2 个不同的脚本中先调用一个方法?
How to call a method before another from 2 different scripts?
我正在尝试从脚本 Dice 调用一个方法,在执行该方法后,变量 diceValue 的值将发生变化。这是我想在脚本 Levizja 的方法中获取和使用的值。
Levizja.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Levizja : MonoBehaviour
{
public Transform[] lojtaret;
public GameObject zari;
private int numer = 0;
public Dice vleraEzarit;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GetComponent<Rigidbody>().AddForceAtPosition(new Vector3(Random.Range(0, 500), Random.Range(0, 500) * 10, Random.Range(0, 500)), new Vector3(0, 0, 0), ForceMode.Force);
Debug.Log("U hodh zari me numer: " + Dice.getValue());
}
}
}
Dice.cs
using System.Collections.Generic;
using UnityEngine;
public class Dice : MonoBehaviour
{
Rigidbody rb;
bool hasLanded, thrown;
Vector3 initPosition;
[SerializeField] private static int diceValue;
private static int numriLojtareve;
//public int diceValue;
public DiceSides[] diceSides;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Reset();
RollDice();
}
if (rb.IsSleeping() && !hasLanded && thrown)
{
hasLanded = true;
rb.useGravity = false;
rb.isKinematic = true;
SideValueCheck();
}
else if (rb.IsSleeping() && hasLanded && diceValue == 0)
RollAgain();
}
void SideValueCheck()
{
diceValue = 0;
foreach(DiceSides side in diceSides)
{
if (side.OnGround())
{
diceValue = side.getValue();
Debug.Log(diceValue + " has been rolled!");
}
}
}
public static int getValue()
{
return diceValue;
}
}
有些方法没有包含只是为了解决这个问题。
我想在 Dice.cs 中执行 Update 方法,这将调用 SideValueCheck 方法。这样变量 diceValue 将被更新。之后,我希望 Levizja.cs 中的 Update 方法以这种方式执行,新值将存储在那里。
发生的事情是我第一次得到值 0 和下一个 运行 我得到骰子的最后一个值。因此,如果第一次降落 3,则显示 0。下次降落 2,则显示 3,依此类推。
理想情况下,该方法应返回 diceValue,并且 Dice 不应有状态。如果你绝对需要 Dice 有一个状态,那么它不应该是静态的。
您可以在Script Execution Order中调整它并强制执行相同事件消息类型的特定顺序(在本例中为Update
) .
但是,这还不够。你宁愿等到骰子有结果。
所以before/instead涉及执行顺序我宁愿重新考虑代码结构并做其他事情。例如。为什么你的两个脚本都需要单独检查用户输入?
而是让一个脚本调用另一个脚本的方法基于事件。也没有理由在此处放置 static
,因为您已经在 vleraEzarit
中引用了 Dice
的实例
public class Dice : MonoBehaviour
{
[Header("References")]
[SerializeField] private Rigidbody _rigidbody;
[SerializeField] private DiceSides[] diceSides;
[Header("Debug")]
[SerializeField] private int diceValue;
private bool hasLanded, thrown;
private Vector3 initPosition;
private int numriLojtareve;
// if you still also want to also provide a read-only access
// to the current value
public int DiceValue => diceValue;
// Event to be invoked everytime there is a new valid dice result
public event Action<int> OnHasResult;
private void Awake()
{
if(!_rigidbody)
{
_rigidbody = GetComponent<Rigidbody>();
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Reset();
RollDice();
}
if (_rigidbody.IsSleeping() && !hasLanded && thrown)
{
hasLanded = true;
_rigidbody.useGravity = false;
_rigidbody.isKinematic = true;
SideValueCheck();
}
else if (_rigidbody.IsSleeping() && hasLanded && diceValue == 0)
{
RollAgain();
}
}
void SideValueCheck()
{
foreach(DiceSides side in diceSides)
{
if (side.OnGround())
{
diceValue = side.getValue();
Debug.Log(diceValue + " has been rolled!");
// Invoke the event and whoever is listening to it will be informed
OnHasResult?.Invoke(diceValue);
// also I would return here since i makes no sense to continue
// checking the other sides if you already have a result
return;
}
}
// I would move this here
// In my eyes it is clearer now that this is the fallback case
// and only happening if nothing in the loop matches
diceValue = 0;
}
}
然后让你的 Levizja
监听这个事件,并且只在它被调用时才执行,例如
public class Levizja : MonoBehaviour
{
[Header("References")]
[SerializeField] private Rigidbody _rigidbody;
[SerializeField] private Transform[] lojtaret;
[SerializeField] private GameObject zari;
[SerializeField] private Dice vleraEzarit;
private int numer = 0;
private void Awake()
{
if(!_rigidbody)
{
_rigidbody = GetComponent<Rigidbody>();
}
// Attach a callback/listener to the event
// just out of a habit I usually remove it first to make sure it can definitely only be added once
vleraEzarit.OnHasResult -= HandleDiceResult;
vleraEzarit.OnHasResult += HandleDiceResult;
}
private void OnDestroy()
{
// make sure to remove callbacks once not needed anymore
// to avoid exceptions
vleraEzarit.OnHasResult -= HandleDiceResult;
}
// This is called ONCE everytime the dice has found a new result
private void HandleDiceResult(int diceValue)
{
_rigidbody.AddForceAtPosition(new Vector3(Random.Range(0, 500), Random.Range(0, 500) * 10, Random.Range(0, 500)), new Vector3(0, 0, 0), ForceMode.Force);
Debug.Log("U hodh zari me numer: " + Dice.getValue());
}
}
我正在尝试从脚本 Dice 调用一个方法,在执行该方法后,变量 diceValue 的值将发生变化。这是我想在脚本 Levizja 的方法中获取和使用的值。
Levizja.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Levizja : MonoBehaviour
{
public Transform[] lojtaret;
public GameObject zari;
private int numer = 0;
public Dice vleraEzarit;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GetComponent<Rigidbody>().AddForceAtPosition(new Vector3(Random.Range(0, 500), Random.Range(0, 500) * 10, Random.Range(0, 500)), new Vector3(0, 0, 0), ForceMode.Force);
Debug.Log("U hodh zari me numer: " + Dice.getValue());
}
}
}
Dice.cs
using System.Collections.Generic;
using UnityEngine;
public class Dice : MonoBehaviour
{
Rigidbody rb;
bool hasLanded, thrown;
Vector3 initPosition;
[SerializeField] private static int diceValue;
private static int numriLojtareve;
//public int diceValue;
public DiceSides[] diceSides;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Reset();
RollDice();
}
if (rb.IsSleeping() && !hasLanded && thrown)
{
hasLanded = true;
rb.useGravity = false;
rb.isKinematic = true;
SideValueCheck();
}
else if (rb.IsSleeping() && hasLanded && diceValue == 0)
RollAgain();
}
void SideValueCheck()
{
diceValue = 0;
foreach(DiceSides side in diceSides)
{
if (side.OnGround())
{
diceValue = side.getValue();
Debug.Log(diceValue + " has been rolled!");
}
}
}
public static int getValue()
{
return diceValue;
}
}
有些方法没有包含只是为了解决这个问题。
我想在 Dice.cs 中执行 Update 方法,这将调用 SideValueCheck 方法。这样变量 diceValue 将被更新。之后,我希望 Levizja.cs 中的 Update 方法以这种方式执行,新值将存储在那里。 发生的事情是我第一次得到值 0 和下一个 运行 我得到骰子的最后一个值。因此,如果第一次降落 3,则显示 0。下次降落 2,则显示 3,依此类推。
理想情况下,该方法应返回 diceValue,并且 Dice 不应有状态。如果你绝对需要 Dice 有一个状态,那么它不应该是静态的。
您可以在Script Execution Order中调整它并强制执行相同事件消息类型的特定顺序(在本例中为Update
) .
但是,这还不够。你宁愿等到骰子有结果。
所以before/instead涉及执行顺序我宁愿重新考虑代码结构并做其他事情。例如。为什么你的两个脚本都需要单独检查用户输入?
而是让一个脚本调用另一个脚本的方法基于事件。也没有理由在此处放置 static
,因为您已经在 vleraEzarit
Dice
的实例
public class Dice : MonoBehaviour
{
[Header("References")]
[SerializeField] private Rigidbody _rigidbody;
[SerializeField] private DiceSides[] diceSides;
[Header("Debug")]
[SerializeField] private int diceValue;
private bool hasLanded, thrown;
private Vector3 initPosition;
private int numriLojtareve;
// if you still also want to also provide a read-only access
// to the current value
public int DiceValue => diceValue;
// Event to be invoked everytime there is a new valid dice result
public event Action<int> OnHasResult;
private void Awake()
{
if(!_rigidbody)
{
_rigidbody = GetComponent<Rigidbody>();
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Reset();
RollDice();
}
if (_rigidbody.IsSleeping() && !hasLanded && thrown)
{
hasLanded = true;
_rigidbody.useGravity = false;
_rigidbody.isKinematic = true;
SideValueCheck();
}
else if (_rigidbody.IsSleeping() && hasLanded && diceValue == 0)
{
RollAgain();
}
}
void SideValueCheck()
{
foreach(DiceSides side in diceSides)
{
if (side.OnGround())
{
diceValue = side.getValue();
Debug.Log(diceValue + " has been rolled!");
// Invoke the event and whoever is listening to it will be informed
OnHasResult?.Invoke(diceValue);
// also I would return here since i makes no sense to continue
// checking the other sides if you already have a result
return;
}
}
// I would move this here
// In my eyes it is clearer now that this is the fallback case
// and only happening if nothing in the loop matches
diceValue = 0;
}
}
然后让你的 Levizja
监听这个事件,并且只在它被调用时才执行,例如
public class Levizja : MonoBehaviour
{
[Header("References")]
[SerializeField] private Rigidbody _rigidbody;
[SerializeField] private Transform[] lojtaret;
[SerializeField] private GameObject zari;
[SerializeField] private Dice vleraEzarit;
private int numer = 0;
private void Awake()
{
if(!_rigidbody)
{
_rigidbody = GetComponent<Rigidbody>();
}
// Attach a callback/listener to the event
// just out of a habit I usually remove it first to make sure it can definitely only be added once
vleraEzarit.OnHasResult -= HandleDiceResult;
vleraEzarit.OnHasResult += HandleDiceResult;
}
private void OnDestroy()
{
// make sure to remove callbacks once not needed anymore
// to avoid exceptions
vleraEzarit.OnHasResult -= HandleDiceResult;
}
// This is called ONCE everytime the dice has found a new result
private void HandleDiceResult(int diceValue)
{
_rigidbody.AddForceAtPosition(new Vector3(Random.Range(0, 500), Random.Range(0, 500) * 10, Random.Range(0, 500)), new Vector3(0, 0, 0), ForceMode.Force);
Debug.Log("U hodh zari me numer: " + Dice.getValue());
}
}