C# 是否有可能在Unity3D中创建更高效的寻的导弹系统?
我已经为我的动作平台编写了一个寻的导弹脚本,我忍不住注意到这可能不是最有效的武器C# 是否有可能在Unity3D中创建更高效的寻的导弹系统?,c#,unity3d,C#,Unity3d,我已经为我的动作平台编写了一个寻的导弹脚本,我忍不住注意到这可能不是最有效的武器 void Start() { target = GameObject.FindGameObjectWithTag("Enemy"); rb = GetComponent<Rigidbody2D>(); } // Update is called once per frame void FixedUpdate() {
void Start()
{
target = GameObject.FindGameObjectWithTag("Enemy");
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
direction = (target.transform.position - transform.position).normalized;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
rotatetoTarget = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, rotatetoTarget, Time.deltaTime * rotationSpeed);
rb.velocity = new Vector2(direction.x * fowrardSpeed, direction.y * fowrardSpeed);
}
void Start()
{
target=GameObject.FindGameObjectWithTag(“敌人”);
rb=GetComponent();
}
//每帧调用一次更新
void FixedUpdate()
{
方向=(target.transform.position-transform.position)。标准化;
浮动角度=数学Atan2(方向y,方向x)*数学Rad2Deg;
旋转目标=四元数角度轴(角度,矢量3向前);
transform.rotation=Quaternion.Slerp(transform.rotation,rotatetoTarget,Time.deltaTime*rotationSpeed);
rb.velocity=新矢量2(方向.x*fowrardSpeed,方向.y*fowrardSpeed);
}
它工作得很好,但也有一些问题。我如何要求它在每次实例化时随机选择不同的敌人?而不是全力以赴对付一个敌人
同样,一旦敌人死亡,它应该选择一个新的目标,但不会执行GameObject。在Update()
中查找()
是件坏事吗?我知道GameObject.Find()
是要避免的,因为它会遍历场景中的所有游戏对象,直到找到它要查找的对象为止,如果需要,应该只在Start()
中使用。现在我不得不在武器实例化时使用GameObject.Find()
,因为我找不到任何其他方法来定位武器的目标。那么,有没有更好的方法来选择一个新的目标,一旦目标被摧毁?我的游戏是一个反应时间很重要的游戏,我不想因为这个武器而造成任何不必要的延迟
谢谢你你可以有一个
EnemyCache
和MisselPawner
脚本
你的EnemyCache
(很可能是一个单身汉)会有一个世界上的敌人列表敌人在繁殖时被添加到该列表中,在死亡时从该列表中移除 然后,您的
MissileSpawner
(或生成投射物的东西)脚本需要在每次生成新导弹时为导弹分配一个目标。它可以通过
EnemyCache
获取新导弹的目标。(您甚至可以筛选列表以获得最近的目标!)
最后,如果旧目标死亡,您的导弹脚本可以从EnemyCache
中获取新目标
总的来说,它应该类似于:
YourMissile.cs
EnemyCache.cs
public class YourMissile : MonoBehaviour {
// ...
GameObject target;
public void Update() {
// target is destroyed or gone
if (target == null) {
SetTargetFromEnemyCache();
}
}
private void SetTargetFromEnemyCache() {
if (EnemyCache.Instance.TryGetFirstEnemy(out Enemy newTarget)) {
target = newTarget.gameObject;
} else {
Debug.LogWarning("No enemy for missile to target!");
}
}
// ...
public void SetTarget(GameObject targetToSet) {
target = targetToSet;
}
// ...
}
public class EnemyCache : MonoBehaviour {
// Singleton
public static EnemyCache Instance { get; private set; }
private List<Enemy> cachedEnemies;
private void Awake() {
Instance = this;
cachedEnemies = new List<Enemy>();
// TODO: Subscribe to a delegate or event, that adds into the 'cachedEnemy' whenever an enemies spawned.
// Also, an event that removes from 'cachedEnemy' when an enemy dies too.
}
// ...
/// <summary>
/// Tries to fetch the first enemy in the cache.
/// </summary>
/// <param name="enemy">The fetched enemy; Null if there was nothing in cache</param>
/// <returns>True if there is an enemy fetched; False if none</returns>
public bool TryGetFirstEnemy(out Enemy enemy) {
if (cachedEnemies.Count > 0) {
enemy = cachedEnemies[0];
return true;
}
enemy = null;
return false;
}
}
public class YourMissileSpawner : MonoBehaviour {
[SerializeField]
private YourMissile missilePrefab;
// ...
public void SpawnProjectile() {
YourMissile newMissile = Instantiate(missilePrefab);
// Set position... etc...
// Try to get a target for the new missile
if (EnemyCache.Instance.TryGetFirstEnemy(out Enemy enemyToTarget)) {
newMissile.SetTarget(enemyToTarget.gameObject);
} else {
Debug.LogWarning("No enemy for newly spawned missile to target!");
}
// NOTE: The above is optional,
// since 'YourMissile' sets a new target from EnemyCache
// if the target is null; (checks per update)
// But I included it here in case you want it to filter
// what kind of enemy it needs to target on start :)
}
}