C# 从下一次实例化更改实例化游戏对象的移动

C# 从下一次实例化更改实例化游戏对象的移动,c#,unity3d,instantiation,game-development,gameobject,C#,Unity3d,Instantiation,Game Development,Gameobject,我用的是Unity和C 在我的游戏中,敌人被反复实例化,并以线性路径向玩家移动。我想让敌人在经过特定时间后以正弦波的方式移动,让游戏变得更加艰难 移动会立即改变,但我希望这种改变从新(下一个)敌人的实例化开始生效,而不是从当前敌人的实例化开始生效 我能做什么 EnemySpawnerscript- private void Start() { timeelapsed = 0f; StartCoroutine(SpawnEnemies(delay)); } private void

我用的是Unity和C

在我的游戏中,敌人被反复实例化,并以线性路径向玩家移动。我想让敌人在经过特定时间后以正弦波的方式移动,让游戏变得更加艰难

移动会立即改变,但我希望这种改变从新(下一个)敌人的实例化开始生效,而不是从当前敌人的实例化开始生效

我能做什么

EnemySpawner
script-

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);
    }
}
敌人移动
脚本:

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);
    }
}
private void Update()
{
t=时间。时间;

如果(EnemySpawner.timeappeased>0f&&EnemySpawner.timeappeased 20f&&EnemySpawner.timeappeased实现这一点的方法有一千种,但我认为一种可能很容易实现和理解的方法可能是设置在你从产卵器实例化新敌人时触发的操作。我很快就为你的敌人编写了一些更改我认为可能对你有帮助的灌肠运动脚本

首先,仇人:

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 );
}
private bool travelInLinearPath=true;
私有void-OnEnable()
{
EnemySpawner.EnemySpawning-=OnEnemySpawning;
EnemySpawner.EnemySpawning+=OnEnemySpawning;
travelInLinearPath=true;
}
公共证券交易()
{
EnemySpawner.EnemySpawning-=OnEnemySpawning;
travelInLinearPath=false;
}
私有无效更新()
{
if(travelInLinearPath)
敌方.transform.Translate(矢量3.forward*速度*时间.deltaTime);
其他的
friend.GetComponent().velocity=Vector3.forward*5+Vector3.left*3*Mathf.Sin(10f*Time.Time);
}
每次启用敌人时,您都会要求在下一个敌人即将繁殖时得到通知。发生这种情况时,您会告诉该敌人从线性移动更改为正弦移动(
travelInLinearPath
)。您还要求在繁殖新敌人时不再通知该敌人(除非您重新启用该敌人)


我也没有讨论你是否应该从敌人的对象池中抓取一个新的敌人。但你希望这样做,这就是为什么我在
OnEnable()
中添加了删除和重新注册事件。你可能希望/需要将该代码放在
Start()中
相反,这取决于您的敌人在游戏后期的实例化和创建。

现在知道请求是针对敌人的“波”,我们需要向每个敌人添加定义波的物品。因此,首先修改
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...
        }

    }
}

我按照你说的做了一切,但是当计时器达到20华氏度时,敌人就停止移动了。请注意1。我在if语句2中仍然有timepassed条件。我使用的是C#4,所以我不得不使用if statemens而不是EnemySpawning?.Invoke();。这些都会导致问题吗。你使用的是Unity的哪个版本?如果你使用的是Unity 2017+,你可以(而且应该)将您的框架版本设置为.Net 4.x。我在Unity网站上读到,实际上鼓励使用.Net标准以实现最大的可移植性,以及更小的构建大小。然后Invoke?将正常工作。您能否解释一下我提供的代码是否不正确,或者您是否希望它执行当前未执行的操作。我现在切换到了Net 4.6。问题仍然存在,因为时间达到20华氏度(我要进行更改的时间),敌人停止移动如果没有移除if条件,敌人停止移动,但是如果我移除if条件并完全按照您所写的编写代码,敌人会立即改变移动,就像我在第一个位置所做的那样。我现在有点困惑。您的示例中有一个计时器,但您也说您希望移动改变w当新敌人出现时,你想在那里有一个定时器吗?或者当新的敌人被催生时,你想要移动吗?
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 );
        }
    }
}