1.NPC定义
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SkillBridge.Message;
namespace Common.Data
{
public enum NpcType //NPC定义 是功能性的 还是任务性的
{
None = 0,
Function,
Task
}
public enum NpcFunction //点击NPC会触发的功能事件
{
None = 0,
InvokeShop,
InvokeInsrance
}
public class NpcDefine
{
public int ID { get; set; }
public string Name { get; set; }
public NpcType Type { get; set; }
public string Description { get; set; }
//基本属性
public NpcFunction Function { get; set; }
public int Integer { get; set; }
}
}
2.NPC管理器
实现管理NPC交互功能
using Common.Data;
using System.Collections.Generic;
namespace Managers
{
class NpcManager:Singleton<NpcManager>
{
public delegate bool NpcActionHandler(NpcDefine npc);
Dictionary<NpcFunction, NpcActionHandler> eventMap = new Dictionary<NpcFunction, NpcActionHandler>();
public NpcDefine GetNpcDefine(int npcID)
{
return DataManager.Instance.Npcs[npcID];
}
public void RegisterNpcEvent(NpcFunction function,NpcActionHandler action)
{
if (!eventMap.ContainsKey(function))
{
eventMap[function] = action;
}
else
eventMap[function] += action;
}
public bool Interactive(int npcID)
{
if (DataManager.Instance.Npcs.ContainsKey(npcID))
{
NpcDefine npc = DataManager.Instance.Npcs[npcID];
return Interactive(npc);
}
return false;
}
public bool Interactive(NpcDefine npc)
{
if (npc.Type == NpcType.Task)
{
return DoTaskInteractive(npc);
}
else if (npc.Type == NpcType.Function)
{
return DoFunctionInteractive(npc);
}
return false;
}
private bool DoTaskInteractive(NpcDefine npc)
{
if(npc.Type!= NpcType.Task)
{
return false;
}
if (!eventMap.ContainsKey(npc.Task))
{
return false;
}
return eventMap[npc.Task](npc);//执行方法管理器中代码所注册的事件函数
}
private bool DoFunctionInteractive(NpcDefine npc)
{
if(npc.Type!= NpcType.Function)
{
return false;
}
if (!eventMap.ContainsKey(npc.Function))
{
return false;
}
return eventMap[npc.Function](npc);
}
}
}
3.NPC控制器
主要控制NPC的行为,比如待机行为,与玩家交互时转向行为,并处理一些交互任务,触碰NPC产生的效果等
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Common.Data;
using Managers;
using Models;
public class NpcController : MonoBehaviour
{
public int npcID;
Animator anim;
NpcDefine npc;
Color originColor;
private bool inInteractive = false;
SkinnedMeshRenderer render;
void Start()
{
anim = this.gameObject.GetComponentInChildren<Animator>();
npc = NpcManager.Instance.GetNpcDefine(npcID);
render = this.gameObject.GetComponentInChildren<SkinnedMeshRenderer>();
originColor = render.sharedMaterial.color;
npc = NpcManager.Instance.GetNpcDefine(this.npcID);
this.StartCoroutine(Actions());
}
IEnumerator Actions()
{
while (true)
{
if (inInteractive)
yield return new WaitForSeconds(2f);
else
yield return new WaitForSeconds(Random.Range(5f,10f));
this.Relatex();
}
}
private void Relatex()
{
anim.SetTrigger("Relax");
}
void Interactive()
{
if (this.inInteractive)
{
this.inInteractive = true;
StartCoroutine(DoInteractive());
}
}
IEnumerator DoInteractive()
{
yield return FaceToPlayer();
if (NpcManager.Instance.Interactive(npc))
{
anim.SetTrigger("Talk");
}
yield return new WaitForSeconds(3f);
this.inInteractive = false;
}
IEnumerator FaceToPlayer()
{
Vector3 faceTo = (User.Instance.CurrentCharacterObj.transform.position - this.transform.position).normalized;
while (Mathf.Abs(Vector3.Angle(this.gameObject.transform.forward, faceTo)) > 5)
{
this.gameObject.transform.forward = Vector3.Lerp(this.gameObject.transform.forward, faceTo, Time.deltaTime * 5f);
yield return null;
}
}
// Update is called once per frame
void OnMouseDown()
{
this.Interactive();
}
private void OnMouseOver()
{
Highlight(true);
}
private void OnMouseEnter()
{
Highlight(true);
}
private void OnMouseExit()
{
Highlight(false);
}
private void Highlight(bool show)
{
if (show)
{
if (render.sharedMaterial.color != Color.white)
{
render.sharedMaterial.color = Color.white;
}
}
else
{
if (render.sharedMaterial.color != originColor)
{
render.sharedMaterial.color = originColor;
}
}
}
}
4.事件方法管理器
namespace FuncManager{
class FuncManager:Singleton<FuncManager>{
public void Init(){
NpcManager.Instance.RegisterNpcEvent(NpcFunction.InvokeShop,OnNpcInvodeShop);
}
private bool OnNpcInvodeShop(NpcDefine npc){
//根据NPC的类型 打开不同的商店UI
//比如 发布任务的 打开的是任务商店 普通商人 打开是道具商店等等
return true;
}
}