【问题标题】:Unity 2d game Player and enemy not movingUnity 2d游戏玩家和敌人不动
【发布时间】:2023-03-22 20:40:02
【问题描述】:

我一直在关注关于统一 2d 游戏的教程。玩家和敌人继承自一个名为 MovingObject 的基类。游戏中的一切正常,除了玩家和敌人不能移动。这是脚本。运动发生在一个网格状的瓷砖系统中。

这是原始教程系列。尝试查看移动对象、玩家和敌人的教程。 https://www.youtube.com/playlist?list=PLX2vGYjWbI0SKsNH5Rkpxvxr1dPE0Lw8F

基础 MovingObject 类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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);
    }

}

protected abstract void OnCantMove<T>(T component)

    where T : Component;


// Update is called once per frame

}

播放器脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Player : MovingObject {

public int wallDamage = 1;
public int pointsPerFood = 10;
public int pointsPerSoda = 20;
public float restartLevelDelay = 1f;

private Animator animator;
private int food;
// Use this for initialization
protected override void Start () {
    animator = GetComponent<Animator>();
    food = GameManager.instance.playerFoodPoints;
    base.Start();

}
private void OnDisable()
{
    GameManager.instance.playerFoodPoints = food;
}
// Update is called once per frame
void Update () {

    if (GameManager.instance.playersTurn)
    {
        return;


    }
    int horizontal = 0;
    int vertical = 0;

    horizontal = (int)Input.GetAxisRaw("Horizontal");
    vertical = (int)Input.GetAxisRaw("Vertical");
    if (horizontal != 0)
    {
        vertical = 0;
    }

    if(horizontal!=0 || vertical != 0)
    {
        AttemptMove<Wall>(horizontal, vertical);
    }

}

protected override void OnCantMove<T>(T component)
{
    Wall hitwall = component as Wall;
    hitwall.damageWall(wallDamage);
    animator.SetTrigger("playerChop");
}
protected override void AttemptMove<T>(int xDir, int yDir)
{
    food--;
    base.AttemptMove<T>(xDir, yDir);
    RaycastHit2D hit;
    CheckIfGameOver();
    GameManager.instance.playersTurn = false;
}

public void LoseFood(int loss)
{
    animator.SetTrigger("playerHit");
    food -= loss;
    CheckIfGameOver();
}

private void OnTriggerEnter2D(Collider2D other)
{
    if (other.tag == "Exit")
    {
        Invoke("Restart", restartLevelDelay);
        enabled = false;
    }   
    else if (other.tag == "Food")
    {
        food += pointsPerFood;
        other.gameObject.SetActive(false);

    }
    else if (other.tag == "Soda")
    {
        food += pointsPerSoda;
        other.gameObject.SetActive(false);
    }
}

private void Restart()
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); 
}

private void CheckIfGameOver()
{
    if (food <= 0)
    {
        GameManager.instance.GameOver();
    }
}
}

敌人脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MovingObject {
public int playerDamage;

private Animator animator;
private Transform target;
private bool skipmove;


// Use this for initialization
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);
}
public void MoveEnemy()
{
    int xDir = 0;
    int yDir = 0;

    if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)
    {
        yDir = target.position.y > transform.position.y ? 1 : -1;

    }
    else
    {
        xDir = target.position.x > transform.position.x ? 1 : -1;
        AttemptMove<Player>(xDir,yDir);
    }
}

protected override void OnCantMove<T>(T component)
{
    Player hitplayer = component as Player;
    animator.SetTrigger("enemyAttack");
    hitplayer.LoseFood(playerDamage);

}

}

我不确定是玩家还是敌人有基本脚本的问题。谁能帮忙。

【问题讨论】:

    标签: c# unity3d 2d


    【解决方案1】:

    一些观察(希望它有所帮助):

    MovingObject.cs - 在 Update() 内部,不应该是这样吗?

    if (!GameManager.instance.playersTurn)
    

    注意我添加了一个“!”在 GameManager 之前

    Player.cs - 在 AttemptMove() 中,您需要像这样调用 Move()...

    Move (xDir, yDir, out hit); 
    

    Enemy.cs

    1) AttemptMove()结束时,应该有:

    skipMove = true;
    

    2) 在 MoveEnemy() 中,最后,这段代码不应该在 else 中,而是在 else 之后:

    AttemptMove<Player>(xDir,yDir); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多