我正在使用Unity和C#。
在我的游戏中,敌人被反复实例化并以线性路径向玩家移动。我想在经过特定时间后使敌人以正弦波运动,以使游戏更加艰难。
动作瞬息万变,但我希望这种变化能从新敌人(下一个)的实例化而不是当前存在的敌人中生效。
我该怎么办?
EnemySpawner
脚本-
private void Start()
{
timeelapsed = 0f;
StartCoroutine(SpawnEnemies(delay));
}
private void Update()
{
timeelapsed += Time.deltaTime;
}
private IEnumerator SpawnEnemies(float delay)
{
while (true)
{
SpawnNewEnemy();
yield return new WaitForSeconds(delay);
}
}
private void SpawnNewEnemy()
{
if (!enemyclone)
{
enemyclone = Instantiate(enemy, enemySpawner.transform.position + offset, Quaternion.identity);
}
}
Enemy Movement
脚本:
private void Update()
{
t = Time.time;
if (EnemySpawner.timeelapsed > 0f && EnemySpawner.timeelapsed <= 20f)
{
enemy.transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
if (EnemySpawner.timeelapsed > 20f && EnemySpawner.timeelapsed <= 40f)
{
enemy.GetComponent<Rigidbody>().velocity = Vector3.forward * 5 + Vector3.left * 3 * Mathf.Sin(10f * t);
}
}
答案 0 :(得分:0)
有上千种方法可以完成此任务,但我认为可能易于实现和理解的方法是设置在从生成器实例化新敌人时触发的Action。我很快就对您的EnemySpawner和EnemyMovement脚本进行了一些更改,认为对您有帮助。
首先,敌人Spawner:
public static event Action EnemySpawning;
void SpawnNewEnemy ( )
{
if ( !enemyclone )
{
EnemySpawning?.Invoke ( );
enemyclone = Instantiate ( enemy, enemySpawner.transform.position + offset, Quaternion.identity );
}
}
现在,敌人运动:
private bool travelInLinearPath = true;
private void OnEnable ( )
{
EnemySpawner.EnemySpawning -= OnEnemySpawning;
EnemySpawner.EnemySpawning += OnEnemySpawning;
travelInLinearPath = true;
}
public void OnEnemySpawning( )
{
EnemySpawner.EnemySpawning-= OnEnemySpawning;
travelInLinearPath = false;
}
private void Update ( )
{
if ( travelInLinearPath )
enemy.transform.Translate ( Vector3.forward * speed * Time.deltaTime );
else
enemy.GetComponent<Rigidbody> ( ).velocity = Vector3.forward * 5 + Vector3.left * 3 * Mathf.Sin ( 10f * Time.time );
}
每次启用一个敌人时,您都要求在即将产生NEXT敌人时得到通知。发生这种情况时,您告诉该敌人从线性运动变为正弦运动(travelInLinearPath
)。您还要求在产生新敌人时不再通知该敌人(除非您重新启用此敌人)。
我也没有考虑您是否应该从敌人的敌人中抢来一个新敌人。但是您希望这样做的原因是为什么我在OnEnable()
的事件中添加了删除并重新注册的原因。您可能希望/需要将代码放置在Start()
中,而不是根据游戏后期敌人的实例化和创建而定。
答案 1 :(得分:0)
现在知道请求是针对敌人的“波浪”,我们需要向每个敌人添加波浪定义项。因此,首先修改EnemyMovement
脚本:
public class EnemyMovement : MonoBehaviour
{
public enum MovementType
{
None = 0,
Linear = 1,
Sinusoidal = 2
// etc, etcc
}
/// <summary>
/// Movement affects the movement type of the enemy.
/// </summary>
public MovementType Movement { get; set; }
/// <summary>
/// This affects the Speed of the Enemy. Used in conunction with Movement to
/// produce the enenmy's wave movement type.
/// </summary>
public float Speed { get; set; }
private Rigidbody rigidBody;
private void Awake ( )
{
rigidBody = GetComponent<Rigidbody> ( );
}
private void Update ( )
{
switch ( Movement)
{
case MovementType.Linear:
transform.Translate ( Vector3.forward * Speed * Time.deltaTime );
break;
case MovementType.Sinusoidal:
// You probably want the Speed property to affect this as well...
rigidBody.velocity = Vector3.forward * 5 + Vector3.left * 3 * Mathf.Sin ( 10f * Time.time );
break;
// Any extra movement types you want here...
}
}
}
然后使用EnemySpawner
脚本来驱动敌人实例化:
public class EnemySpawner : MonoBehaviour
{
public float Delay;
public float StartSpeed;
public GameObject enemy;
public GameObject enemySpawner;
public Vector3 offset;
private float timeElapsed;
private float currentSpeed;
private EnemyMovement.MovementType currentMovement;
void Start ( )
{
timeElapsed = 0f;
currentSpeed = StartSpeed;
StartCoroutine ( SpawnEnemies ( Delay ) );
currentMovement = EnemyMovement.MovementType.Linear;
}
void Update ( )
{
timeElapsed += Time.deltaTime;
// We can determine at what time the Wave parameters change here.
if ( timeElapsed >= 40.0f )
{
currentSpeed += 10.0f; // Add speed, for example.
}
else if ( timeElapsed >= 20.0f )
{
currentMovement = EnemyMovement.MovementType.Sinusoidal;
}
}
IEnumerator SpawnEnemies ( float delay )
{
while ( true )
{
var enemyClone = Instantiate ( enemy, enemySpawner.transform.position + offset, Quaternion.identity );
var movement = enemyClone.GetComponent<EnemyMovement> ( );
// We now set what the enemy uses as the Wave values.
movement.Speed = currentSpeed;
movement.Movement = currentMovement;
yield return new WaitForSeconds ( delay );
}
}
}