如何修改这个统一教程脚本?

时间:2015-04-21 06:59:39

标签: generics types unity3d

所以有一个Unity官方教程,2D流氓就好。 http://unity3d.com/learn/tutorials/projects/2d-roguelike

在这些系列中,我想修改,改善敌人的AI用于学习目的。

当敌人遇到墙壁时,我想要绕开或摧毁墙壁。

所以第一个敌人需要识别墙壁。

所以我这样修改了它,但它没有用。有没有人知道出了什么问题?

MovingObject.cs

using UnityEngine;
using System.Collections;

public abstract class MovingObject : MonoBehaviour {
public float moveTime = 0.1f;
public LayerMask blockingLayer;
private BoxCollider2D boxCollider;
private Rigidbody2D rb2D;
private float inverseMoveTime;

// Use this for initialization
protected virtual void Start () {
    boxCollider = GetComponent<BoxCollider2D>();
    rb2D = GetComponent<Rigidbody2D>();
    inverseMoveTime = 1f / moveTime;
}
protected bool Move(int xDir, int yDir, out RaycastHit2D hit){
    Vector2 start = transform.position;
    Vector2 end = start+new Vector2(xDir, yDir);
    boxCollider.enabled = false;
    hit = Physics2D.Linecast(start, end, blockingLayer);
    boxCollider.enabled = true;
    if(hit.transform == null){
        StartCoroutine(SmoothMovement(end));
        return true;
    }
    return false;
}
protected IEnumerator SmoothMovement(Vector3 end){
    float sqrRemainingDistance = (transform.position-end).sqrMagnitude;
    while(sqrRemainingDistance > float.Epsilon){
        Vector3 newPosition = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime);
        rb2D.MovePosition(newPosition);
        sqrRemainingDistance = (transform.position-end).sqrMagnitude;
        yield return null;
    }
}
protected virtual void AttemptMove<T> (int xDir, int yDir) where T : Component{
    RaycastHit2D hit;
    bool canMove = Move (xDir, yDir, out hit);
    if(hit.transform == null)
        return;

    T hitComponent = hit.transform.GetComponent<T>();

    if(!canMove && hitComponent != null){
        OnCantMove(hitComponent);
        if(hitComponent is Wall)
            OnCantMoveEnemy(hitComponent);
    }
}

protected abstract void OnCantMove<T> (T component) where T : Component;
protected abstract void OnCantMoveEnemy <T> (T component)   where T : Component;
}

和Enemy.cs

using UnityEngine;
using System.Collections;

public class Enemy : MovingObject {
public int playerDamage;
private Animator animator;
private Transform target;
private bool skipMove;
public AudioClip enemyAttack1;
public AudioClip enemyAttack2;

protected override void Start () {
    GameManager.instance.AddEnemyToList(this);
    animator = GetComponent<Animator>();
    target = GameObject.FindGameObjectWithTag("Player").transform;
    base.Start();
}

protected override void AttemptMove<T> (int xDir, int yDir){
    if(skipMove){
        skipMove = false;
        return;
    }
    base.AttemptMove<T>(xDir, yDir);

    skipMove = true;

}
public void MoveEnemy(){
    int xDir = 0;       int yDir = 0;
    if((Mathf.Abs(target.position.x - transform.position.x) > float.Epsilon)){
        xDir = target.position.x > transform.position.x ? 1 : -1;  
    }
    if(Mathf.Abs(target.position.y - transform.position.y) > float.Epsilon){
        yDir = target.position.y > transform.position.y ? 1 : -1;
    }   
    Debug.Log("ydir is "+yDir+" / xdir is "+xDir);
    AttemptMove<Player>(xDir, yDir); 
    AttemptMove<Wall>(xDir, yDir); 
} 

protected override void OnCantMove<T>(T component){ 
    Player hitPlayer = component as Player; 
    animator.SetTrigger("enemyAttack");
    hitPlayer.LoseFood(playerDamage); 
    SoundManager.instance.RandomizeSfx(enemyAttack1, enemyAttack2);
}
protected override void OnCantMoveEnemy<T>(T component){ 
    Wall hitWall = component as Wall;
    Debug.Log("hit wall is "+hitWall.name);
}

}

1 个答案:

答案 0 :(得分:-1)

您不需要添加任何其他方法。

我通过在AttemptMove<T>的{​​{1}}中添加几行来做到这一点:

MovingObject.cs

并通过以下方式扩展现有条件块:

Wall wallComponent = hit.transform.GetComponent<Wall>();

请记住,从现在开始,必须使用“墙”式预制件来创建每道可破坏的墙。

然后,您可以使用条件块修改else if (hit.transform.ToString().Substring(0,4) == "Wall") { OnCantMove(wallComponent); } Enemy.cs方法:

OnCantMove<T>

并使用脚本中已经包含的代码填充这些内容。