如何修改此统一教程脚本? [英] How to revise this unity tutorial script?
问题描述
因此有一个Unity官方教程,类似于2D流氓. http://unity3d.com/learn/tutorials/projects/2d-roguelike
So there is a Unity official tutorial, 2D rogue like. http://unity3d.com/learn/tutorials/projects/2d-roguelike
在这些系列中,我想修改,改善敌人的AI以用于学习.
In these series, I want to revise, improve enemy's AI for study purpose.
当敌人遇到隔离墙时,我想绕开或摧毁隔离墙.
I want, when an enemy meets a wall, to circumvent or destroy the wall.
因此,第一个敌人需要认出这堵墙.
So the first enemy needs to recognize the wall.
所以我这样修改了它,但是没有用.有人知道出什么事了吗?
So I revised it like this, but it didn't work. Does anyone have an idea what's going wrong?
MovingObject.cs
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);
}
}
推荐答案
您不需要添加任何其他方法.
You don't need to add any extra methods.
我通过在MovingObject.cs
的AttemptMove<T>
中添加几行来做到这一点:
I've done this by adding few lines in AttemptMove<T>
in MovingObject.cs
:
Wall wallComponent = hit.transform.GetComponent<Wall>();
并通过以下方式扩展现有条件块:
and by expanding already existing conditional block with:
else if (hit.transform.ToString().Substring(0,4) == "Wall")
{
OnCantMove(wallComponent);
}
请记住,从现在开始,必须使用墙"式预制件来创建每道可破坏的墙.
Keep in mind that from now on every wall that should be destructible has to be created from "Wall" prefab.
然后,您可以使用条件块修改Enemy.cs
OnCantMove<T>
方法:
Then you can modify your Enemy.cs
OnCantMove<T>
method with a conditional block:
if (component is Player){...}
else if (component is Wall){...}
并使用您脚本中已有的代码填充这些内容.
And fill those with code that you already have in your scripts.
这篇关于如何修改此统一教程脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!