unity学习|2021-9-7 破防了!!!崩溃瞬间,欲哭无泪
家人们,破防啦!! 今天从早上起来就开始画地图,做机关。直到后来发现,左右移动的机关不能带着主角一起移动。
然后经过百度搜索,知道了使用双碰撞体比地面检测盒子要好用一点。然后就开始了我的作死之旅。
通过一番改动,发现梯子上的空气墙设定很难实现,于是想Ctrl+Z回退,却发现回退不了。然后我就改改改,但是怎么改都改不回来,都会出现bug。
然后我想,昨天晚上我保存过,大不了就今天白干嘛!
【unity学习|2021-9-7 破防了!!!崩溃瞬间,欲哭无泪】然后我就点不保存退出,再次打开的时候发现,不仅今天的所有工作白干,而且代码还回不到原来的没有bug的状态。
家人们,我破防了呀!!!
所以大家千万要记得做大的改动之前,一定要备份一下!!!
算了,分享几个我觉得我处理的不错的代码。
关于怪物AI的设定,使用了面向对象的思想。
主要还是延时执行,使在每帧执行的函数Update里不每帧都执行位移,而是在特定条件下才执行。这点我想了很久。
- 总类:怪物类 :用于其他怪物继承
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();
_rigidbody2D = GetComponent();
player = GameObject.FindGameObjectWithTag("Player");
playerController = player.GetComponent();
Grade = GameObject.FindGameObjectWithTag("Grade").GetComponent();
id_attack = Animator.StringToHash("attack");
distance = 100;
//解决怪物出生时就攻击的bugoriginPosition = 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().GetBool("fall")&& player.transform.position.y - transform.position.y >= 0.1f)
|| (player.transform.position.y - transform.position.y >= 0.5f && player.GetComponent().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;
}
}
}
}
- 青蛙类: 开始时待机,玩家进入攻击范围后,向玩家方向跳跃,两秒后停止,判断玩家方向,再次进行攻击,直至玩家脱离青蛙攻击范围。
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>().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.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.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;
}
}
推荐阅读
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 如何更好的去学习
- 【韩语学习】(韩语随堂笔记整理)
- 焦点学习田源分享第267天《来访》