通过一阵子的学习,我是这么认为的,因为该教程是难度两星的教程 ,也就是适合学了一阵子基础组件以后的学习者
(什么都不会的学习者要是学这套课程会困难重重,如果你什么都不会那么需要学习一星教程)
所以该课程没有那么多manger,代码也不那么面向对象,但是从怪物类之后就开始有相关的内容了,建议熟练面向对象的知识以后再来学习后面的内容
C# & Unity 面向对象补全计划 之 继承(字段与属性)_unity继承属性-CSDN博客
本文实现结果如下
1.怪物基类
思考
1.怪物要有速度,所以设置三种默认速度,追击速度,当前速度
2.怪物要有朝向,可以实时获取当前的朝向
3.怪物要移动,所以需要刚体组件
4.怪物要有动画,所以需要动画组件
5.怪物需要切换速度,所以要追加条件
代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Monster : MonoBehaviour
{
[Header("速度")]
public float normalSpeed;
public float chaseSpeed;
public float currentSpeed;
[Header("面朝向")]
private Vector3 headFor;
[Header("组件")]
private Rigidbody2D rb;
private Animator animator;
private void Awake() {
rb = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
}
private void Update() {
//实时面朝向
headFor = new Vector3(-this.transform.localScale.x,0,0);
}
private void FixedUpdate() {
Move();
}
public void Move()
{
//移动算式
rb.velocity=new Vector2( currentSpeed* headFor.x*Time.deltaTime,rb.velocity.y);
}
}
2.野猪的动画
思考
1.动画应该以什么条件切换?
因为怪物不像玩家一样用按键控制加速,是监测范围内出现玩家后,触发追击,反之亦然,所以适合用bool值来切换速度响应状态,也就是切换动画
(当然麦扣老师的考量就是继承怪物类的多种怪物,不靠一种速度模式触发,这样说也合理)
2.撞墙怎么办?
撞墙和检测玩家后切换动画状态属于同一种解决方法,都是用范围检测去判断
问题1
怪物的移动方法与散步逻辑,这里还要加入检测到玩家后跑步逻辑
结合问题2的撞墙范围检测来讲,相信并不难写了
//移动方法
protected virtual void Move()
{
//移动算式
rb.velocity=new Vector2( currentSpeed* headFor.x*Time.deltaTime,rb.velocity.y);
if(!(physicscheck.isLeftWall&& physicscheck.isRightWall))
{isWalk = true;
animator.SetBool("walk", isWalk); }
else
{
isWalk = false;
}
}
问题2
撞墙检测
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class PhysicsCheck : MonoBehaviour
{
//地面检测
public bool isGround;
public bool isLeftWall;
public bool isRightWall;
//检测半径
public float raduis;
//检测层级
private LayerMask ground;
//检测偏移量
[Header("偏移量")]
public Vector2 positionWithOffset;
public Vector2 leftOffset;
public Vector2 rightOffset;
private void Start() {
ground = LayerMask.GetMask("Ground");
}
private void Update() {
Check();
}
private void Check()
{
isGround = Physics2D.OverlapCircle((Vector2)this.transform.position + positionWithOffset, raduis, ground);
isLeftWall = Physics2D.OverlapCircle((Vector2)this.transform.position + leftOffset, raduis, ground);
isRightWall = Physics2D.OverlapCircle((Vector2)this.transform.position + rightOffset, raduis, ground);
Debug.Log("isGround: " + isGround);
Debug.Log("isLeftWall: " + isLeftWall);
Debug.Log("isRightWall: " + isRightWall);
}
private void OnDrawGizmosSelected() {
Gizmos.DrawWireSphere((Vector2)this.transform.position + positionWithOffset, raduis);
Gizmos.DrawWireSphere((Vector2)this.transform.position + leftOffset, raduis);
Gizmos.DrawWireSphere((Vector2)this.transform.position + rightOffset, raduis);
}
}
撞墙等待后转身的计时器
//撞墙等待转身方法 protected void WaitAndTurn() { if(waitState) { waitClock -= Time.deltaTime; if(waitClock<= 0) { waitState=false; waitClock = waitTime; // 重置计时器 this.transform.localScale = new Vector3(headFor.x,1,1); } } }
撞墙以后原地等待同步动画的逻辑
//实时面朝向
headFor = new Vector3(-this.transform.localScale.x,0,0);
if ((headFor.x > 0 && physicscheck.isRightWall) || (headFor.x < 0 && physicscheck.isLeftWall)) {
waitState = true;
animator.SetBool("walk", false);
}
//延迟转身
WaitAndTurn();