2021-9-7 破防了!!!崩溃瞬间,欲哭无泪

家人们,破防啦!!

今天从早上起来就开始画地图,做机关。直到后来发现,左右移动的机关不能带着主角一起移动。

然后经过百度搜索,知道了使用双碰撞体比地面检测盒子要好用一点。然后就开始了我的作死之旅。

通过一番改动,发现梯子上的空气墙设定很难实现,于是想Ctrl+Z回退,却发现回退不了。然后我就改改改,但是怎么改都改不回来,都会出现bug。

然后我想,昨天晚上我保存过,大不了就今天白干嘛!

然后我就点不保存退出,再次打开的时候发现,不仅今天的所有工作白干,而且代码还回不到原来的没有bug的状态。

家人们,我破防了呀!!!

所以大家千万要记得做大的改动之前,一定要备份一下!!!

算了,分享几个我觉得我处理的不错的代码。

关于怪物AI的设定,使用了面向对象的思想。

主要还是延时执行,使在每帧执行的函数Update里不每帧都执行位移,而是在特定条件下才执行。这点我想了很久。

  1. 总类:怪物类 :用于其他怪物继承
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;


// 怪物总类别,唯一不能在面板中更改而需要写代码的只是怪物的攻击方式不同
public class MonsterAI : MonoBehaviour
{
    [Header("与怪物距离多少进入攻击距离")]
    public float attackDistance = 4.0f;

    [Header("攻击持续时间")]
    public float attackTime = 2.5f;

    [Header("攻击后休息时间")]
    public float changeDirectionTime = 2.0f;

    [Header("怪物移动的速度")]
    public float MoveSpeed = 3.0f;

    [Header("消灭怪物的分数")]
    public float grade = 20;

    [Header("死亡预制体")]
    public GameObject death;  // 必须要通过拖拽,在代码中利用tag寻找是找不到的

    protected float attackDirection = 1;  // 怪物攻击方向,默认向左

    protected float distance; // 怪物与玩家的水平距离

    protected Animator _animator;

    protected Rigidbody2D _rigidbody2D;

    protected GameObject player;

    protected PlayerController playerController;

    protected Text Grade;

    protected int id_attack;

    protected bool isAttack; 

    protected bool isPatrol = true;  // 是否正在巡逻

    protected bool targeted = false; // 是否锁定目标,为了巡逻和攻击之间的转换

    protected Vector2 originPosition;

    protected Vector2 deathPosition;

    protected virtual void Awake()
    {
        _animator = GetComponent<Animator>();
        _rigidbody2D = GetComponent<Rigidbody2D>();
        
        player = GameObject.FindGameObjectWithTag("Player");
        playerController = player.GetComponent<PlayerController>();
        
        Grade = GameObject.FindGameObjectWithTag("Grade").GetComponent<Text>();

        id_attack = Animator.StringToHash("attack");

        distance = 100;  //解决怪物出生时就攻击的bug

        originPosition = transform.position;
    }

    // Update is called once per frame
    protected virtual void Update()
    {
        if (player != null)
        {
            distance = transform.position.x - player.transform.position.x;
        }
        if (transform.position.y < -10 || transform.position.y > 10)
        {
            Destroy(gameObject);
        }
        if (Mathf.Abs(distance) <= attackDistance)
        {
            isPatrol = false;
        }
        else
        {
            isPatrol = true;
        }
    }

    protected virtual void Attack()
    {
        JudgeDirection();
        isAttack = true;
        _animator.SetBool(id_attack, isAttack);
        Invoke("Rest", attackTime); // 延时执行休息,也是为了保证攻击时间
    }

    // 休息,不再攻击
    protected virtual void Rest()
    {
        _animator.SetBool(id_attack, false);
        Invoke("AttackAgain", changeDirectionTime);  // 延时执行判断方向
    }

    // 再次攻击,判断方向
    protected virtual void AttackAgain()
    {
        isAttack = false;  // 延时执行使isAttack=false的原因是为了执行完休息动画,也是为了让怪物不瞬间再次进入攻击状态
    }

    // 休息时判断方向
    protected virtual void JudgeDirection() 
    {
        if (distance >= 0)
        {
            attackDirection = 1;
        }
        else
        {
            attackDirection = -1;
        }
        _rigidbody2D.transform.localScale = new Vector3(attackDirection, 1, 1);
    }


    protected virtual void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.tag == "Player")
        {
            if ((player.GetComponent<Animator>().GetBool("fall")  && player.transform.position.y - transform.position.y >= 0.1f)
                || (player.transform.position.y - transform.position.y >= 0.5f && player.GetComponent<Animator>().GetBool("jump")))
            {
                playerController.Jump();
                Grade.text = (int.Parse(Grade.text) + grade).ToString();
                deathPosition = transform.position;
                Instantiate(death, deathPosition, Quaternion.identity);
                Destroy(gameObject);
            }
            else
            {
                playerController.isHurt = true;
            }
        }
    }
}

  1. 青蛙类: 开始时待机,玩家进入攻击范围后,向玩家方向跳跃,两秒后停止,判断玩家方向,再次进行攻击,直至玩家脱离青蛙攻击范围。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Frog : MonsterAI
{
    [Header("跳跃力")]
    public float JumpForce = 2.0f;

    [Header("地面检测层")]
    public LayerMask groundMask;

    [Header("地面检测盒子的高度")]
    public float BoxHeight = 0.2f;

    private Vector2 frogsize; // 青蛙大小

    private Vector2 boxsize; // 检测盒子尺寸

    protected override void Awake()
    {
        base.Awake();
        frogsize = GetComponent<SpriteRenderer>().bounds.size;
        boxsize = new Vector2(frogsize.x * 0.2f, BoxHeight);  // 设置检测盒的大小
    }

    protected override void Update()
    {
        base.Update();
    }

    void FixedUpdate()
    {
        if (!isPatrol && !isAttack)
        {
            Attack();
        }
    }

    protected override void Attack()
    {
        base.Attack();
    }

    protected override void Rest()
    {
        base.Rest();
    }

    protected override void AttackAgain()
    {
        base.AttackAgain();
    }

    protected override void JudgeDirection()
    {
        base.JudgeDirection();
    }

    protected override void OnCollisionEnter2D(Collision2D collision)
    {
        base.OnCollisionEnter2D(collision);
    }

    void Jump()
    {
        if (IsOnGround())
        {
            _rigidbody2D.velocity = new Vector2(MoveSpeed * -attackDirection, JumpForce);
        }
    }

    private bool IsOnGround()
    {
        Vector2 boxcenter = (Vector2)transform.position + (Vector2.down * frogsize.y * 0.3f);
        return Physics2D.OverlapBox(boxcenter, boxsize, 0, groundMask);
    }

    private void OnDrawGizmos()
    {
        Vector2 boxcenter = (Vector2)transform.position + (Vector2.down * frogsize.y * 0.3f);
        Gizmos.color = Color.blue;
        Gizmos.DrawWireCube(boxcenter, boxsize);
    }
}

  1. 负鼠类:开始时左右巡逻,待玩家进入攻击范围后,迅速向玩家冲刺。冲刺1.5秒后,判断方向,再次攻击,直至玩家脱离攻击范围,负鼠再次确定左右边界,进行巡逻。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Opossum : MonsterAI
{
    private float left, right;  // 巡逻的左右边界

    private int patrolDir = 1; // 巡逻方向,默认向左

    private float Timer = 3.0f; // 3秒防止巡逻时卡住

    protected override void Awake()
    {
        base.Awake();
    }

    protected override void Update()
    {
        base.Update();
    }

    void FixedUpdate()
    {
        if (!isPatrol)
        {
            if (!isAttack)
            {
                Attack();
            }
            else
            {
                transform.position += Vector3.left * attackDirection * MoveSpeed * Time.deltaTime;
            }
        }
        else if (isPatrol)
        {
            Patrol();
        }
    }

    private void Patrol()
    {
        Timer -= Time.deltaTime;
        if (!targeted)
        {
            targeted = true;
            originPosition = transform.position;
        }
        _rigidbody2D.transform.localScale = new Vector3(patrolDir, 1, 1);
        left = originPosition.x - 4;
        right = originPosition.x + 4;
        transform.position += Vector3.left * patrolDir * MoveSpeed / 2 * Time.deltaTime;
        if (transform.position.x < left || transform.position.x > right || Timer <= 0)
        {
            patrolDir = -patrolDir;
            Timer = 3.0f;
        }
    }

    protected override void Attack()
    {
        base.Attack();
        targeted = false;
    }

    protected override void Rest()
    {
        base.Rest();
    }

    protected override void AttackAgain()
    {
        base.AttackAgain();
    }

    protected override void JudgeDirection()
    {
        base.JudgeDirection();
    }

    protected override void OnCollisionEnter2D(Collision2D collision)
    {
        base.OnCollisionEnter2D(collision);
    }
}

  1. 老鹰类:开始时上下巡逻,待玩家进入攻击范围后,迅速飞向玩家进行攻击。冲刺1.5秒后,判断方向,再次攻击,直至玩家脱离攻击范围,老鹰再次确定上下边界,进行巡逻。 (我觉得难点是老鹰的重力处理以及与玩家碰撞后的弹力处理)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Eagle : MonsterAI
{
    private float up, down;  // 巡逻的上下边界

    private int patrolDir = 1; // 巡逻方向,默认向上

    private Vector2 currentDir;

    protected override void Awake()
    {
        base.Awake();
    }

    protected override void Update()
    {
        base.Update();
    }

    void FixedUpdate()
    {
        if (!isPatrol)
        {
            if (!isAttack)
            {
                Attack();
            }
            else 
            {
                transform.position += (Vector3)currentDir * MoveSpeed * Time.deltaTime;
            }
        }
        else if (isPatrol)
        {
            Patrol();
        }
    }

    private void Patrol()
    {
        if (!targeted)
        {
            targeted = true;
            _rigidbody2D.velocity = Vector2.zero;
            originPosition = transform.position;
        }
        _rigidbody2D.transform.localScale = new Vector3(attackDirection, 1, 1);
        up = originPosition.y + 3;
        down = originPosition.y - 3;
        transform.position += Vector3.up * patrolDir * MoveSpeed / 3  * Time.deltaTime;

        if (transform.position.y < down || transform.position.y > up)
        {
            patrolDir = -patrolDir;
        }
    }

    protected override void Attack()
    {
        if (player != null)   // 防止人物在鹰的范围内被击败导致的空引用问题
        {
            currentDir = Vector3.Normalize(player.transform.position - transform.position); // 重新转换上下边界
        }
        base.Attack();
        targeted = false;
    }

    protected override void Rest()
    {
        base.Rest();
        Patrol();
    }

    protected override void AttackAgain()
    {
        base.AttackAgain();
    }

    protected override void JudgeDirection()
    {
        base.JudgeDirection();
    }

    protected override void OnCollisionEnter2D(Collision2D collision)
    {
        base.OnCollisionEnter2D(collision);
        _rigidbody2D.velocity = Vector2.zero;
    }
}

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

giegie界清流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值