麦扣 3DRPG游戏开发教程 14集

麦扣 3DRPG游戏开发教程 14集

🎮

随机巡逻点

绘制攻击范围

OnDrawGizmosSelected()更节约资源


解决怪位置卡死的方法

NavMesh.SamplePosition(点坐标,out 输出点信息,搜索范围,检测的导航层),这个函数会返回一个bool值,这个bool值表示 能否在范围内搜索到 距离目标点最近的一个导航点,然后将这个导航点的信息放到 输出点信息中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void GetNewWayPoint()
{
float randomX = UnityEngine.Random.Range(-patrolRange, patrolRange);
float randomZ = UnityEngine.Random.Range(-patrolRange, patrolRange);
// Vector3 randomPoint = new Vector3(transform.position.x + randomX, transform.position.y,
// transform.position.z + randomZ);
Vector3 randomPoint = new Vector3(guardPos.x + randomX,transform.position.y,
guardPos.z + randomZ);
//y还是保持它自身的刚体影响,因为地面上有坑坑洼洼
// todo: 可能出现的问题,不能这么简单就得到这个点
// wayPoint = randomPoint;
NavMeshHit hit;
wayPoint = NavMesh.SamplePosition(randomPoint, out hit,patrolRange,1)?hit.position:transform.position;
//这个函数返回一个bool值,√使得怪物的最终点为这个,否则停留于原地
}

//让怪走走停停看看 符合巡逻的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;


public enum EnemyStates
{
GUARD,
PATROL,
CHASE,
DEAD
}

[RequireComponent(typeof(NavMeshAgent))]
public class EnemyController : MonoBehaviour
{
private NavMeshAgent agent;
private EnemyStates enemyStates;
private Animator anim;
[Header("Basic Settings")] public float sightRadius;

private float speed;
public bool isGuard;

private GameObject attackTarget;

//⭐⭐⭐怪的巡逻⭐⭐⭐
public float lookAtTime;
private float remainLookAtTime;
[Header("Patrol State")] public float patrolRange;
private Vector3 wayPoint;
private Vector3 guardPos;

//bool配合动画
private bool isWalk;

private bool isChase;
private bool isFollow;

private void Awake()
{
//自有组件、自有变量放在awake
anim = GetComponent<Animator>();
agent = GetComponent<NavMeshAgent>();
speed = agent.speed;
guardPos = transform.position;
remainLookAtTime = lookAtTime;
}

private void Start()
{
if (isGuard)
{
enemyStates = EnemyStates.GUARD;
}
else
{
enemyStates = EnemyStates.PATROL;
GetNewWayPoint();
}
}

private void Update()
{
SwitchStates();
SwitchAnimation();
}

void SwitchAnimation()
{
anim.SetBool("Walk", isWalk);
anim.SetBool("Chase", isChase);
anim.SetBool("Follow", isFollow);
}

//状态切换机器
void SwitchStates()
{
//如果发现player 切换到chase
if (FoundPlayer())
{
enemyStates = EnemyStates.CHASE;
}

//--------------------------
switch (enemyStates)
{
case EnemyStates.GUARD:
break;
case EnemyStates.PATROL:
isChase = false;
agent.speed = speed * .5f;
//判断一下指定的点 如果相同就给一个新的点,不同就往这儿移动
if (Vector3.Distance(wayPoint, transform.position) <= agent.stoppingDistance)
{
isWalk = false;
if (remainLookAtTime > 0)
remainLookAtTime -= Time.deltaTime;
else
GetNewWayPoint();
}
else
{
isWalk = true;
agent.destination = wayPoint;
}

break;
case EnemyStates.CHASE:
//追逐玩家
//在攻击范围内攻击
//配合动画
isWalk = false;
isChase = true;

agent.speed = speed;
if (!FoundPlayer())
{
//拉脱回上一个状态
isFollow = false;
if (remainLookAtTime > 0){
agent.destination = transform.position;
remainLookAtTime -= Time.deltaTime;
}
else if (isGuard)⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
{
enemyStates = EnemyStates.GUARD;
}
else
{
enemyStates = EnemyStates.PATROL;
}
}
else
{
isFollow = true;
agent.destination = attackTarget.transform.position;
}

break;
case EnemyStates.DEAD:
break;
}
}

bool FoundPlayer()
{
var colliders = Physics.OverlapSphere(transform.position, sightRadius);
foreach (var target in colliders)
{
if (target.CompareTag("Player"))
{
attackTarget = target.gameObject;
return true;
}
}

attackTarget = null;
return false;
}

// todo: 随机生成一个点
void GetNewWayPoint()
{
remainLookAtTime = lookAtTime;
float randomX = UnityEngine.Random.Range(-patrolRange, patrolRange);
float randomZ = UnityEngine.Random.Range(-patrolRange, patrolRange);
// Vector3 randomPoint = new Vector3(transform.position.x + randomX, transform.position.y,
// transform.position.z + randomZ);
Vector3 randomPoint = new Vector3(guardPos.x + randomX, transform.position.y,
guardPos.z + randomZ);
//y还是保持它自身的刚体影响,因为地面上有坑坑洼洼
// todo: 可能出现的问题,不能这么简单就得到这个点
// wayPoint = randomPoint;
NavMeshHit hit;
wayPoint = NavMesh.SamplePosition(randomPoint, out hit, patrolRange, 1) ? hit.position : transform.position;
//这个函数返回一个bool值,√使得怪物的最终点为这个,否则停留于原地
}

private void OnDrawGizmosSelected()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(transform.position, sightRadius);
}
}

麦扣 3DRPG游戏开发教程 14集

https://www.llbwy.com/2022/10/15/b站m_studio3drpg14/

作者

发布于

2022-10-15

更新于

2022-12-19

许可协议