fix:补充ai行为流程
This commit is contained in:
@@ -120,7 +120,7 @@ public class PlayerAI : Agent
|
||||
}
|
||||
|
||||
[Server]
|
||||
public virtual void OnSpawn(int id, PlayerAIType type, int lvl)
|
||||
public virtual void OnSpawn(int id, PlayerAIType type, int lvl,GameObject target)
|
||||
{
|
||||
base.OnSpawn();
|
||||
this.id = id;
|
||||
@@ -142,7 +142,10 @@ public class PlayerAI : Agent
|
||||
if (aiPath != null) aiPath.enabled = true;
|
||||
if (rvoController != null) rvoController.enabled = true;
|
||||
if (selfCollider != null) selfCollider.enabled = true;
|
||||
if (behaviorTree != null) behaviorTree.enabled = true; // 仅 Host(Server)上运行 BT
|
||||
if (behaviorTree != null) {
|
||||
behaviorTree.enabled = true;
|
||||
behaviorTree.SetVariable("target",(SharedGameObject)target);
|
||||
}
|
||||
// 初始血量已在 Agent.OnSpawn 中设置为 originHealth / health
|
||||
}
|
||||
}
|
||||
@@ -217,7 +220,7 @@ public class PlayerAI : Agent
|
||||
if (!isServer) return; // 攻击判定/伤害应由 Server 执行(Host 权威)
|
||||
AnimatorComponent.SetInteger("state",1);
|
||||
//调用枪械开枪脚本
|
||||
gun.Shoot();
|
||||
gun.AiShoot();
|
||||
}
|
||||
|
||||
|
||||
@@ -231,4 +234,14 @@ public class PlayerAI : Agent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ChangeKillEnemyTime()
|
||||
{
|
||||
behaviorTree.SetVariable("CountdownTime",(SharedFloat)10f);
|
||||
}
|
||||
|
||||
public void KillEnemyEvent()
|
||||
{
|
||||
//gun.Shoot()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
using BehaviorDesigner.Runtime;
|
||||
using BehaviorDesigner.Runtime.Tasks;
|
||||
using DragonLi.Core;
|
||||
using UnityEngine;
|
||||
|
||||
public class Actions
|
||||
@@ -78,15 +79,14 @@ public class Actions
|
||||
|
||||
public class EnemyMoveToward : Action
|
||||
{
|
||||
public SharedFloat dis;
|
||||
public SharedVector3 targetPos;
|
||||
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
Enemy enemy = transform.GetComponent<Enemy>();
|
||||
if (enemy == null) return TaskStatus.Failure;
|
||||
Vector3 targetPos = transform.position + new Vector3(0, 0, -1) * dis.Value;
|
||||
enemy.ai.isStopped = false;
|
||||
enemy.ai.destination = targetPos;
|
||||
enemy.ai.destination = targetPos.Value;
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
@@ -127,21 +127,31 @@ public class Actions
|
||||
|
||||
public class PlayerAIAttack : Action
|
||||
{
|
||||
public SharedGameObject target;
|
||||
public SharedVector3 targetPos;
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
PlayerAI playerAi = transform.GetComponent<PlayerAI>();
|
||||
if (playerAi == null) return TaskStatus.Failure;
|
||||
playerAi.StopAttack();
|
||||
transform.LookAt(new Vector3(targetPos.Value.x, transform.position.y, targetPos.Value.z));
|
||||
if (target.Value != null)
|
||||
{
|
||||
transform.LookAt(new Vector3(target.Value.transform.position.x, transform.position.y, target.Value.transform.position.z));
|
||||
}
|
||||
playerAi.DoAttack();
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerAIStopAttack: Action
|
||||
{
|
||||
public SharedGameObject target;
|
||||
public SharedVector3 targetPos;
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
PlayerAI playerAi = transform.GetComponent<PlayerAI>();
|
||||
if (playerAi == null) return TaskStatus.Failure;
|
||||
target.Value = null;
|
||||
playerAi.StopAttack();
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
@@ -187,4 +197,84 @@ public class Actions
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 正常射击寻找敌人
|
||||
/// </summary>
|
||||
public class TeammateFindTarget : Action
|
||||
{
|
||||
public SharedVector3 targetPos;
|
||||
|
||||
public float normalHitMin = 0.1f; // 10%
|
||||
public float normalHitMax = 0.2f; // 20%
|
||||
private float hitRate;
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
// 每次开始时刷新命中率
|
||||
hitRate = Random.Range(normalHitMin, normalHitMax);
|
||||
}
|
||||
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
var tran = GameManager.Ins.GetEnemy(transform);
|
||||
if (tran == null) return TaskStatus.Failure;
|
||||
|
||||
bool isHit = Random.value < hitRate;
|
||||
|
||||
if (isHit)
|
||||
{
|
||||
targetPos.Value = tran.transform.position; // 命中敌人
|
||||
}
|
||||
else
|
||||
{
|
||||
// 偏移未命中
|
||||
Vector2 randomCircle = Random.insideUnitCircle.normalized;
|
||||
Vector3 offset = new Vector3(randomCircle.x, Random.Range(-0.5f, 0.5f), randomCircle.y) * 3f;
|
||||
targetPos.Value = tran.transform.position + offset;
|
||||
}
|
||||
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 百分百杀死敌人
|
||||
/// </summary>
|
||||
public class TeammateSupportKill : Action
|
||||
{
|
||||
public SharedFloat CountdownTime; // 倒计时秒数
|
||||
public SharedGameObject Target;
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
if (GameManager.Ins == null) return TaskStatus.Failure;
|
||||
var enemy = GameManager.Ins.GetEnemy(transform);
|
||||
if (enemy != null)
|
||||
{
|
||||
var enemyComponent = enemy.GetComponent<Enemy>();
|
||||
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
||||
{
|
||||
if (enemyComponent != null && enemyComponent.state != EnemyState.Die)
|
||||
{
|
||||
enemyComponent.Die(transform.position,null);
|
||||
Debug.Log($"{gameObject.name} 倒计时结束,击杀一名敌人!");
|
||||
CountdownTime.Value=10;
|
||||
}
|
||||
}, 3f);
|
||||
Target = enemy;
|
||||
}
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public class CountdownTimeAction: Action
|
||||
{
|
||||
public SharedFloat CountdownTime; // 倒计时秒数
|
||||
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
CountdownTime.Value-=Time.deltaTime;
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,4 +196,16 @@ public class Conditionals
|
||||
return GameManager.Ins.IsHaveEnemy()? TaskStatus.Success : TaskStatus.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 击杀敌人倒计时
|
||||
/// </summary>
|
||||
public class CheckKillEnemyCountdownTime: Conditional
|
||||
{
|
||||
public SharedFloat CountdownTime;
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
return CountdownTime.Value<=0? TaskStatus.Success : TaskStatus.Failure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,9 +123,12 @@ public class Bullet : NetworkBehaviour
|
||||
#endregion
|
||||
|
||||
[Server]
|
||||
public virtual void OnSpawn(int ownerIndex, Vector3 recoil, float recoilCount)
|
||||
public virtual void OnSpawn(int curOwnerIndex, Vector3 recoil, float recoilCount)
|
||||
{
|
||||
this.ownerIndex = ownerIndex;
|
||||
|
||||
|
||||
if (curOwnerIndex != -1)
|
||||
ownerIndex = curOwnerIndex;
|
||||
rigidbodyComponent.velocity = recoil.normalized * recoilCount;
|
||||
rigidbodyComponent.rotation = Quaternion.LookRotation(recoil.normalized);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,11 @@ using System.Collections.Generic;
|
||||
using Mirror;
|
||||
using UnityEngine;
|
||||
|
||||
public enum DefendEventType
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//事件基类
|
||||
public class DefendEvent : NetworkBehaviour
|
||||
{
|
||||
@@ -16,6 +21,19 @@ public class DefendEvent : NetworkBehaviour
|
||||
public bool isOver;
|
||||
|
||||
public bool isStart;
|
||||
|
||||
public virtual void Init(List<Enemy> enemies, List<NPC> curNpcList)
|
||||
{
|
||||
enemyList = enemies;
|
||||
npcList = curNpcList;
|
||||
isOver = false;
|
||||
isStart = false;
|
||||
}
|
||||
|
||||
public virtual void StartEvent()
|
||||
{
|
||||
isStart = true;
|
||||
}
|
||||
|
||||
public virtual void EndEvent(){}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class StartEvent : DefendEvent
|
||||
public class NormalEvent : DefendEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ public class Enemy : Agent
|
||||
}
|
||||
|
||||
[Server]
|
||||
public virtual void OnSpawn(int id, EnemyType type, int lvl)
|
||||
public virtual void OnSpawn(int id, EnemyType type, int lvl,Vector3 targetPos)
|
||||
{
|
||||
base.OnSpawn();
|
||||
this.id = id;
|
||||
@@ -161,7 +161,11 @@ public class Enemy : Agent
|
||||
if (aiPath != null) aiPath.enabled = true;
|
||||
if (rvoController != null) rvoController.enabled = true;
|
||||
if (selfCollider != null) selfCollider.enabled = true;
|
||||
if (behaviorTree != null) behaviorTree.enabled = true; // 仅 Host(Server)上运行 BT
|
||||
if (behaviorTree != null)
|
||||
{
|
||||
behaviorTree.enabled = true;
|
||||
behaviorTree.SetVariable("targetPos",(SharedVector3)targetPos);
|
||||
} // 仅 Host(Server)上运行 BT
|
||||
// 初始血量已在 Agent.OnSpawn 中设置为 originHealth / health
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ public class SDRRMI : Enemy
|
||||
public SDRRMIHand rightHand;
|
||||
|
||||
[Server]
|
||||
public override void OnSpawn(int id, EnemyType type, int lvl)
|
||||
public override void OnSpawn(int id, EnemyType type, int lvl,Vector3 targetPos)
|
||||
{
|
||||
base.OnSpawn(id, type, lvl);
|
||||
base.OnSpawn(id, type, lvl,targetPos);
|
||||
leftHand.atk = atk;
|
||||
leftHand.gameObject.SetActive(true);
|
||||
rightHand.atk = atk;
|
||||
|
||||
@@ -62,11 +62,10 @@ public class GameLocal : MonoBehaviour
|
||||
|
||||
[NonSerialized]
|
||||
public GameObject DieUI;
|
||||
|
||||
|
||||
public Transform[] enemyStartPos;
|
||||
public Transform[] enemyEndPos;
|
||||
public Transform[] playerAiPos;
|
||||
public Transform[] playerAiEndPos;
|
||||
public Transform[] gunPropPos;
|
||||
|
||||
public Transform doorPos;
|
||||
|
||||
@@ -115,6 +115,7 @@ public class Launcher : NetworkBehaviour
|
||||
Shoot(curOwnerIndex);
|
||||
}
|
||||
|
||||
|
||||
[Server]
|
||||
public bool Shoot(int ownerIndex)
|
||||
{
|
||||
|
||||
8
Assets/_DefendNJ/Scripts/Manager.meta
Normal file
8
Assets/_DefendNJ/Scripts/Manager.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4001bf13659a2af438166907115a6968
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
13
Assets/_DefendNJ/Scripts/Manager/DefendEventManager.cs
Normal file
13
Assets/_DefendNJ/Scripts/Manager/DefendEventManager.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DefendEventManager : MonoBehaviour
|
||||
{
|
||||
public Dictionary<int,DefendEvent> defendEventDic = new Dictionary<int,DefendEvent>();
|
||||
|
||||
public void StartEvent(int id)
|
||||
{
|
||||
defendEventDic[id].StartEvent();
|
||||
}
|
||||
}
|
||||
11
Assets/_DefendNJ/Scripts/Manager/DefendEventManager.cs.meta
Normal file
11
Assets/_DefendNJ/Scripts/Manager/DefendEventManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2809f452877aef4d8b8ff4e955a57f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -39,6 +39,12 @@ public enum GameState
|
||||
Wave=5,
|
||||
}
|
||||
|
||||
public enum GameMode
|
||||
{
|
||||
OnePlayer=0,
|
||||
TwoPlayers=1,
|
||||
}
|
||||
|
||||
|
||||
public class GameManager : NetworkBehaviour
|
||||
{
|
||||
@@ -84,6 +90,8 @@ public class GameManager : NetworkBehaviour
|
||||
|
||||
public Dictionary<int, Player> players = new Dictionary<int, Player>();
|
||||
|
||||
public GameMode gameMode = GameMode.OnePlayer;
|
||||
|
||||
/// <summary>
|
||||
/// 敌人自增
|
||||
/// </summary>
|
||||
@@ -175,6 +183,7 @@ public class GameManager : NetworkBehaviour
|
||||
{
|
||||
PlaySound2DRPC("1.1");
|
||||
}, 10f);
|
||||
CreatePlayerAi();
|
||||
SetGameState(GameState.Wave);
|
||||
RpcMessageRound();
|
||||
}
|
||||
@@ -186,8 +195,8 @@ public class GameManager : NetworkBehaviour
|
||||
{
|
||||
roundIndex++;
|
||||
SetGameState(GameState.Wave);
|
||||
roundWaveTime = 15;
|
||||
curRoundWaveTime = 12;
|
||||
roundWaveTime = 5;
|
||||
curRoundWaveTime = 2;
|
||||
RpcMessageRound();
|
||||
}
|
||||
|
||||
@@ -195,6 +204,7 @@ public class GameManager : NetworkBehaviour
|
||||
public void GameStart()
|
||||
{
|
||||
gameState = GameState.Playing;
|
||||
gameMode=players.Count<=1 ? GameMode.OnePlayer : GameMode.TwoPlayers;
|
||||
vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime;
|
||||
isStart = true;
|
||||
ChangeBgmRpc(1);
|
||||
@@ -328,35 +338,45 @@ public class GameManager : NetworkBehaviour
|
||||
{
|
||||
GameObject enemy = Instantiate(EnemyPres[info.EnemyList[i]]);
|
||||
NetworkServer.Spawn(enemy);
|
||||
int posId = Random.Range(0, 4);
|
||||
int posX=Random.Range(-1, 1);
|
||||
int posZ=Random.Range(-1, 1);
|
||||
enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,posZ);
|
||||
int posId =i/3;
|
||||
int posX=i%3==0? 0: i%3==1 ? 1 : -1;
|
||||
enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position;
|
||||
enemy.transform.eulerAngles = new Vector3(0, 0, 0);
|
||||
enemyIndex++;
|
||||
Enemy enemyScript = enemy.GetComponent<Enemy>();
|
||||
enemyScript.OnSpawn(enemyIndex, (EnemyType)info.EnemyList[i], 1);
|
||||
enemyScript.OnSpawn(enemyIndex, (EnemyType)info.EnemyList[i], 1,GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,0));
|
||||
EnemyList.Add(enemyIndex, enemyScript);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建场景
|
||||
/// 创建辅助AI
|
||||
/// </summary>
|
||||
public void CreatePlayerAi()
|
||||
{
|
||||
for (int i = 0; i < players.Count; i++)
|
||||
if (gameMode == GameMode.OnePlayer)
|
||||
{
|
||||
GameObject playerAi = Instantiate(playerAiPres[i]);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
GameObject playerAi = Instantiate(playerAiPres[i]);
|
||||
NetworkServer.Spawn(playerAi);
|
||||
playerAi.transform.position = GameLocal.Ins.playerAiPos[i].position;
|
||||
playerAi.transform.eulerAngles = new Vector3(0, 0, 0);
|
||||
PlayerAI enemyScript = playerAi.GetComponent<PlayerAI>();
|
||||
enemyScript.OnSpawn(i,(PlayerAIType)i, 1,GameLocal.Ins.playerAiEndPos[i].gameObject);
|
||||
PlayerAiList.Add(i, enemyScript);
|
||||
}
|
||||
}
|
||||
else if(gameMode == GameMode.TwoPlayers)
|
||||
{
|
||||
GameObject playerAi = Instantiate(playerAiPres[0]);
|
||||
NetworkServer.Spawn(playerAi);
|
||||
playerAi.transform.position = GameLocal.Ins.playerAiPos[i].position;
|
||||
playerAi.transform.position = GameLocal.Ins.playerAiPos[0].position;
|
||||
playerAi.transform.eulerAngles = new Vector3(0, 0, 0);
|
||||
enemyIndex++;
|
||||
PlayerAI enemyScript = playerAi.GetComponent<PlayerAI>();
|
||||
enemyScript.OnSpawn(enemyIndex,(PlayerAIType)i, 1);
|
||||
PlayerAiList.Add(enemyIndex, enemyScript);
|
||||
curRoundEnemyCount++;
|
||||
enemyScript.OnSpawn(0,0, 1,GameLocal.Ins.playerAiEndPos[0].gameObject);
|
||||
PlayerAiList.Add(0, enemyScript);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,18 +385,18 @@ public class GameManager : NetworkBehaviour
|
||||
/// </summary>
|
||||
public void CreateBoss()
|
||||
{
|
||||
GameObject enemy = Instantiate(EnemyPres[(int)EnemyType.ZombieBoss]);
|
||||
NetworkServer.Spawn(enemy);
|
||||
int posId = Random.Range(0, 4);
|
||||
int posX=Random.Range(-1, 1);
|
||||
int posZ=Random.Range(-1, 1);
|
||||
enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,posZ);
|
||||
enemy.transform.eulerAngles = new Vector3(0, 0, 0);
|
||||
enemyIndex++;
|
||||
Enemy enemyScript = enemy.GetComponent<Enemy>();
|
||||
enemyScript.OnSpawn(enemyIndex, EnemyType.ZombieBoss, 1);
|
||||
EnemyList.Add(enemyIndex, enemyScript);
|
||||
curRoundEnemyCount++;
|
||||
// GameObject enemy = Instantiate(EnemyPres[(int)EnemyType.ZombieBoss]);
|
||||
// NetworkServer.Spawn(enemy);
|
||||
// int posId = Random.Range(0, 4);
|
||||
// int posX=Random.Range(-1, 1);
|
||||
// int posZ=Random.Range(-1, 1);
|
||||
// enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,posZ);
|
||||
// enemy.transform.eulerAngles = new Vector3(0, 0, 0);
|
||||
// enemyIndex++;
|
||||
// Enemy enemyScript = enemy.GetComponent<Enemy>();
|
||||
// enemyScript.OnSpawn(enemyIndex, EnemyType.ZombieBoss, 1);
|
||||
// EnemyList.Add(enemyIndex, enemyScript);
|
||||
// curRoundEnemyCount++;
|
||||
}
|
||||
|
||||
public void CreateExplosion(Transform pos)
|
||||
@@ -548,7 +568,7 @@ public class GameManager : NetworkBehaviour
|
||||
|
||||
if (curRoundEnemyCount<=0)
|
||||
{
|
||||
CreateGunProp();
|
||||
//CreateGunProp();
|
||||
CreateNextRound();
|
||||
}
|
||||
}
|
||||
@@ -733,6 +753,14 @@ public class GameManager : NetworkBehaviour
|
||||
return nearestPlayer;
|
||||
}
|
||||
|
||||
public void ChangePlayerAiCountdownTime()
|
||||
{
|
||||
foreach (var ai in PlayerAiList.Values)
|
||||
{
|
||||
ai.ChangeKillEnemyTime();
|
||||
}
|
||||
}
|
||||
|
||||
public Transform GetPlayerPos()
|
||||
{
|
||||
int rand = Random.Range(0, 100);
|
||||
@@ -773,6 +801,7 @@ public class GameManager : NetworkBehaviour
|
||||
GameObject enemyUI = EnemyUIList[id].gameObject;
|
||||
EnemyUIList.Remove(id);
|
||||
NetworkServer.Destroy(enemyUI);
|
||||
ChangePlayerAiCountdownTime();
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
Reference in New Issue
Block a user