一、框架视图
二、主要代码
BaseControllerManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;
public abstract class BaseControllerManager : MonoBehaviour
{
private VRTK_ControllerEvents controllerEvents;
public abstract void GripReleased();
public abstract void GripPressed();
public abstract void TouchpadReleased();
public abstract void TouchpadPressed();
public abstract void TriggerReleased();
public abstract void TriggerPressed();
private void Awake()
{
controllerEvents = GetComponent();
controllerEvents.GripPressed += ControllerEvents_GripPressed;
controllerEvents.GripReleased += ControllerEvents_GripReleased;
controllerEvents.TriggerPressed += ControllerEvents_TriggerPressed;
controllerEvents.TriggerReleased += ControllerEvents_TriggerReleased;
controllerEvents.TouchpadPressed += ControllerEvents_TouchpadPressed;
controllerEvents.TouchpadReleased += ControllerEvents_TouchpadReleased;
}
private void ControllerEvents_TouchpadReleased(object sender, ControllerInteractionEventArgs e)
{
TouchpadReleased();
}
private void ControllerEvents_TouchpadPressed(object sender, ControllerInteractionEventArgs e)
{
TouchpadPressed();
}
private void ControllerEvents_TriggerReleased(object sender, ControllerInteractionEventArgs e)
{
TriggerReleased();
}
private void ControllerEvents_TriggerPressed(object sender, ControllerInteractionEventArgs e)
{
TriggerPressed();
}
private void ControllerEvents_GripReleased(object sender, ControllerInteractionEventArgs e)
{
GripReleased();
}
private void ControllerEvents_GripPressed(object sender, ControllerInteractionEventArgs e)
{
GripPressed();
}
}
Game:
BodyPartDrop
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 受伤后掉落
///
public class BodyPartDrop : MonoBehaviour
{
public GameObject go_Firend;
public void SetFriend(GameObject go)
{
go_Firend = go;
}
///
/// 受伤后掉落的处理
///
public void Hit()
{
BodyPartDrop[] arr = transform.parent.GetComponentsInChildren();
foreach (var item in arr) //中间掉落 下面也要跟着掉落
{
item.go_Firend.SetActive(false);
item.transform.parent = null;
item.transform.GetChild(0).gameObject.SetActive(true);
item.gameObject.AddComponent();
Destroy(item);
}
}
}
Bomb
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 爆炸
///
public class Bomb : MonoBehaviour
{
public bool IsThrow = false; //是都可以投掷
public float BrustTime = 5f; //爆炸等待时间
public GameObject effect_Brust; //爆炸特效
private float m_Timer = 0.0f; //计时器
private void FixedUpdate()
{
if (IsThrow) //判断是否可以爆炸 在手管理类的时候投掷炸弹设置为true HandManger170
{
m_Timer += Time.deltaTime;
if (m_Timer >= BrustTime)
{
Instantiate(effect_Brust, transform.position, transform.rotation); //实例化特效
Destroy(gameObject);
EventCenter.Broadcast(EventDefine.BombBrust, transform.position);//广播发生爆炸特效的事件 当前爆炸位置的信息
}
}
}
}
Book
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum BookType
{
StartBook,
AboutBook,
GestureBook
}
///
/// 书籍管理类
///
public class Book : MonoBehaviour
{
public BookType m_BookType;
public Vector3 m_StratPos;
public Quaternion m_StartRot;
///
/// 判断书本是否触发到书台
///
public bool m_IsTrigger = false;
///
/// 触发的书台物体
///
private GameObject go_StandBook;
private void Awake()
{
m_StratPos = transform.position;
m_StartRot = transform.rotation;
}
private void Update()
{
if (transform.parent != null && go_StandBook != null)
{
if (transform.parent != go_StandBook.transform)
{
IsActiveUI(false);
}
}
}
///
/// 放置书本
///
public void Put()
{
if (go_StandBook.GetComponentInChildren() != null)
{
go_StandBook.GetComponentInChildren().Release();
}
transform.parent = go_StandBook.transform;
transform.position = go_StandBook.transform.GetChild(0).position;
transform.rotation = go_StandBook.transform.GetChild(0).rotation;
IsActiveUI(true);
}
///
/// 书本归为
///
public void Release()
{
transform.parent = null;
transform.position = m_StratPos;
transform.rotation = m_StartRot;
IsActiveUI(false);
}
///
/// 是否激活当前书本对应的UI界面
///
///
private void IsActiveUI(bool value)
{
switch (m_BookType)
{
case BookType.StartBook:
EventCenter.Broadcast(EventDefine.IsShowStartPanel, value);
break;
case BookType.AboutBook:
EventCenter.Broadcast(EventDefine.IsShowAboutPanel, value);
break;
case BookType.GestureBook:
EventCenter.Broadcast(EventDefine.IsShowGesturePanel, value);
break;
}
}
private void OnTriggerStay(Collider other)
{
if (other.tag == "BookStand")
{
m_IsTrigger = true;
go_StandBook = other.gameObject;
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "BookStand")
{
m_IsTrigger = false;
go_StandBook = null;
}
}
}
GestureRecognition
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Edwon.VR;
using Edwon.VR.Gesture;
///
/// 检测手势
///
public class GestureRecognition : BaseGestureRecognition
{
public override void Awake()
{
base.Awake();
EventCenter.AddListener(EventDefine.IsStartGestureRecognition, IsStartGestureRecognition); //后面可以是方法或者直接赋值 布尔变量
}
public override void OnDestroy()
{
base.OnDestroy();
EventCenter.RemoveListener(EventDefine.IsStartGestureRecognition, IsStartGestureRecognition);
}
///
/// 是否开始手势识别
///
///
private void IsStartGestureRecognition(bool value)
{
if (value)
{
BeginRecognition();
}
else
{
gestureRig.uiState = VRGestureUIState.Idle;
}
}
public override void OnGestureDetectedEvent(string gestureName, double confidence) //检测手势事件
{
string skillName = GestureSkillManager.GetSkillNameByGestureName(gestureName); //获取技能的名称
GameObject skill = ResourcesManager.LoadObj(skillName); //加载技能预制体
Instantiate(skill, new Vector3(Camera.main.transform.position.x, 0, Camera.main.transform.position.z), skill.transform.rotation); //实例化技能 注意生成的位置
}
}
GestureSkillManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Edwon.VR;
using Edwon.VR.Gesture;
///
/// 手势技能管理
///
public class GestureSkillManager
{
///
/// 手势名与技能名的字典
///
private static Dictionary m_GestureSkillDic = new Dictionary();
private static VRGestureSettings gestureSettings;
private static string SkillName = "Skill";
static GestureSkillManager()
{
gestureSettings = Utils.GetGestureSettings();
m_GestureSkillDic = GetGestureSkillDic();
}
///
/// 获取手势名与技能名之间的关系
///
///
private static Dictionary GetGestureSkillDic()
{
Dictionary gestureSkillDic = new Dictionary();
//规则:手势名-技能名;手势名-技能名
if (PlayerPrefs.HasKey("GestureSkill"))
{
string gestureSkill = PlayerPrefs.GetString("GestureSkill");
string[] arr = gestureSkill.Split(';');
foreach (var item in arr)
{
string[] tempArr = item.Split('-');
gestureSkillDic.Add(tempArr[0], tempArr[1]);
}
}
else
{
for (int i = 0; i < gestureSettings.gestureBank.Count; i++)
{
gestureSkillDic.Add(gestureSettings.gestureBank[i].name, SkillName + (i + 1).ToString());
}
SaveGestureSkillDic(gestureSkillDic);
}
return gestureSkillDic;
}
///
/// 保存手势与技能之间的关系
///
private static void SaveGestureSkillDic(Dictionary dic)
{
string temp = "";
int index = 0;
foreach (var item in dic)
{
//规则:手势名-技能名;手势名-技能名
temp += item.Key + "-" + item.Value;
index++;
if (index != dic.Count)
temp += ";";
}
PlayerPrefs.SetString("GestureSkill", temp);
}
///
/// 通过手势名获取技能名
///
public static string GetSkillNameByGestureName(string gestureName)
{
if (m_GestureSkillDic.ContainsKey(gestureName))
{
return m_GestureSkillDic[gestureName];
}
return null;
}
///
/// 更换手势与技能之间的关系(更换技能)
///
///
///
public static void ChangeSkill(string gestureName, string newSkillName)
{
if (m_GestureSkillDic.ContainsKey(gestureName))
{
m_GestureSkillDic[gestureName] = newSkillName;
SaveGestureSkillDic(m_GestureSkillDic);
}
}
///
/// 通过手势名获取技能图片
///
///
public static Sprite GetSkilSpriteByGestureName(string gestureName)
{
if (m_GestureSkillDic.ContainsKey(gestureName))
{
return ResourcesManager.LoadSprite(m_GestureSkillDic[gestureName]);
}
return null;
}
}
HPManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
///
/// 血量管理类
///
public class HPManager : MonoBehaviour
{
public int HP = 10000;
private void Awake()
{
EventCenter.AddListener(EventDefine.UpdateHP, UpdateHP);
EventCenter.AddListener(EventDefine.BombBrust, BombBrust);
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.UpdateHP, UpdateHP);
EventCenter.RemoveListener(EventDefine.BombBrust, BombBrust);
}
///
/// 炸弹爆炸
///
///
private void BombBrust(Vector3 brustPos)
{
if (Vector3.Distance(transform.position, brustPos) < 10.0f)
{
UpdateHP(-20);
}
}
///
/// 更新血量
///
///
private void UpdateHP(int count)
{
if (count < 0)
{
if (HP <= Mathf.Abs(count))//血量小于0 挂掉
{
//死亡
HP = 0;
Death(); //加载当前活跃的场景
}
else
{
HP += count; //增加血量
}
}
else
{
HP += count;
}
EventCenter.Broadcast(EventDefine.UpdateHpUI, HP); //广播更新血量的事件码
}
private void Death()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); //加载当前场景
}
}
Magazine
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 弹夹管理类
///
public class Magazine : MonoBehaviour
{
///
/// 子弹数量
///
private int BulletCount = 6;
///
/// 设置子弹的方法
///
///
public void SetBulletCount(int count)
{
BulletCount = count;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Backet")
{
if (transform.parent != null && transform.parent.GetComponentInChildren() != null)
{
Destroy(gameObject);
transform.parent.GetComponentInChildren().Catch(false);
//加子弹
AmmoManager.Instance.UpdateBullet(BulletCount);
}
}
}
}
Pistol
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
///
/// 手枪
///
public class Pistol : MonoBehaviour
{
public EventDefine ShotEvent;//射击事件 这两个要在面板上指定是哪个事件 分别是左右手
public EventDefine ReloadMagazineEvent;//换弹夹 指定类型在面板上赋值 为了方便广播事件
public Transform m_StartPos; //起始位置
public GameObject go_Point;
public GameObject effect_HitOtherMask; //黑洞
public GameObject effect_HitOther;//烟雾特效
public GameObject effect_Fire; //火的特效
public GameObject effect_Blood; //血特效
public GameObject go_Magazine;//弹夹
public AudioClip audio_Shot; //射击声音片段
private LineRenderer m_LineRenderer; //渲染
private Animator m_Anim;//动画
private RaycastHit m_Hit;//射线
public int m_CurrentBulletCount = 6; //弹夹数量
private AudioSource m_AudioSource;
private void Awake()
{
m_AudioSource = GetComponent(); //获取组件
m_LineRenderer = GetComponent();
m_Anim = GetComponent();
EventCenter.AddListener(ShotEvent, Shot);//添加射击监听 广播事件是分别执行左右手
EventCenter.AddListener(ReloadMagazineEvent, ReloadMagazine);//添加换弹夹事件 广播时候左右手按下圆盘时候
}
private void OnDestroy()
{
EventCenter.RemoveListener(ShotEvent, Shot);//移除监听射击事件
EventCenter.RemoveListener(ReloadMagazineEvent, ReloadMagazine); //移除换弹夹事件
}
///
/// 换弹夹
///
private void ReloadMagazine()
{
//代表是Main场景 则忽略
if (SceneManager.GetActiveScene().buildIndex == 0) return;
//如果手枪是隐藏的,则忽略
if (gameObject.activeSelf == false) return;
//如果当前正在播放开火的动画,则忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Fire")) return;
//如果当前正在播放换弹夹的动画,则忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Reload")) return;
if (GameObject.FindObjectOfType() != null)
if (GameObject.FindObjectOfType().transform.localScale != Vector3.zero)
return;
int temp = m_CurrentBulletCount; //当前数量
m_CurrentBulletCount = AmmoManager.Instance.ReloadMagazine(); //单例模式
if (m_CurrentBulletCount != 0)
{
m_Anim.SetTrigger("Reload");
GameObject go = Instantiate(go_Magazine, transform.Find("Magazine").position, transform.Find("Magazine").rotation);
go.GetComponent().SetBulletCount(temp);
}
}
///
/// 射击
///
private void Shot()
{
//代表是Main场景 则忽略
if (SceneManager.GetActiveScene().buildIndex == 0) return;
//如果手枪是隐藏的,则忽略
if (gameObject.activeSelf == false) return;
//如果当前正在播放开火的动画,则忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Fire")) return;
//如果当前正在播放换弹夹的动画,则忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Reload")) return;
if (m_CurrentBulletCount <= 0) return;
m_CurrentBulletCount--; //子弹数量减减
//播放射击动画
m_Anim.SetTrigger("Shot");
if (m_AudioSource.isPlaying == false)
{
m_AudioSource.clip = audio_Shot;
m_AudioSource.Play();
}
Destroy(Instantiate(effect_Fire, m_StartPos.position, m_StartPos.rotation), 1.5f);
if (m_Hit.collider != null)
{
//是否是僵尸
if (m_Hit.collider.tag == "Zombie")
{
if (m_Hit.transform.GetComponent() != null)
{
m_Hit.transform.GetComponent().Hit();
}
if (m_Hit.transform.GetComponent() != null)
{
m_Hit.transform.GetComponent().Hit();
}
//实例化血的特效,1.5秒之后销毁
Destroy(Instantiate(effect_Blood, m_Hit.point, Quaternion.LookRotation(m_Hit.normal)), 2f); //旋转看向受伤的地方
}
else
{
GameObject mask = Instantiate(effect_HitOtherMask, m_Hit.point, Quaternion.LookRotation(m_Hit.normal));//黑洞遮罩
mask.transform.parent = m_Hit.transform;
Destroy(Instantiate(effect_HitOther, m_Hit.point, Quaternion.LookRotation(m_Hit.normal)), 2);//实例化烟雾 2秒后消失
}
}
}
///
/// 画线
///
private void DrawLine(Vector3 startPos, Vector3 endPos, Color color)
{
m_LineRenderer.positionCount = 2;
m_LineRenderer.SetPosition(0, startPos);
m_LineRenderer.SetPosition(1, endPos);
m_LineRenderer.startWidth = 0.001f;
m_LineRenderer.endWidth = 0.001f;
m_LineRenderer.material.color = color;
}
private void FixedUpdate()
{
if (Physics.Raycast(m_StartPos.position, m_StartPos.forward, out m_Hit, 100000, 1 << 0 | 1 << 2)) //检测第一层 第二层 如果1是0 的话表示是不检测
{
DrawLine(m_StartPos.position, m_Hit.point, Color.green);
go_Point.SetActive(true);
go_Point.transform.position = m_Hit.point;
}
else
{
DrawLine(m_StartPos.position, m_StartPos.forward * 100000, Color.red);
go_Point.SetActive(false);
}
}
}
ZombieController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
///
/// 控制器
///
public class ZombieController : MonoBehaviour
{
public float m_WalkSpeed = 0.8f;//走路速度
public float m_RunSpeed = 2;//跑步速度
public float m_DistanceJudge = 1f; //距离判断
public float m_HitDealyTime = 2f; //受伤延迟
///
/// 攻击时间间隔
///
public float m_AttackInterval = 3f;
public AudioClip audio_Attack;
public AudioClip audio_Walk;
private NavMeshAgent m_Agent; //导航网格
private Animator m_Anim;
private Transform m_Target; //相机位置
///
/// 是否第一次攻击
///
private bool m_IsFirstAttack = true;
private float m_Timer = 0.0f;
///
/// 是否正在攻击
///
private bool m_IsAttacking = false;
///
/// 是否正在受伤中
///
private bool m_IsHitting = false;
///
/// 僵尸是否死亡
///
private bool m_IsDeath = false;
public bool IsDeath
{
get
{
return m_IsDeath;
}
}
private AudioSource m_AudioSource; //声效
private void Awake()
{
m_AudioSource = GetComponent();
m_Anim = GetComponent();
m_Agent = GetComponent();
m_Target = Camera.main.transform; //相机信息
EventCenter.AddListener(EventDefine.BombBrust, BombBrust); //监听炸弹爆炸的事件码
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.BombBrust, BombBrust);//移除炸弹爆炸的事件码
}
private void Start()
{
RandomWalkOrRun();
}
private void FixedUpdate()
{
if (m_IsDeath) return;
if (m_IsHitting) return;
Vector3 tempTargetPos = new Vector3(m_Target.position.x, transform.position.y, m_Target.position.z); //获取物体的位置
if (Vector3.Distance(transform.position, tempTargetPos) < m_DistanceJudge) //判断相机跟物体之间的距离
{
if (m_Agent.isStopped == false)
{
m_Agent.isStopped = true; //停止导航
}
if (m_IsAttacking == false)
{
m_Timer += Time.deltaTime;
if (m_Timer >= m_AttackInterval)
{
m_Timer = 0.0f;
m_IsAttacking = true; //调用攻击的函数
Attack();
}
}
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("AttackBlendTree") == false) //第0层的播放动画名称
{
if (m_IsFirstAttack) //标志位 只加一次0.5f 之后不加 避免判断距离越来越大
{
m_DistanceJudge += 0.5f; //避免根据距离动画来回播放
m_IsFirstAttack = false;
m_IsAttacking = true;
Attack();
}
else
{
m_IsAttacking = false;
}
}
}
else
{ //没达到距离 继续寻路
if (m_Agent.isStopped)
{
m_DistanceJudge -= 0.5f; //避免根据距离动画来回播放
m_Agent.isStopped = false; //继续寻路
m_IsFirstAttack = true;
RandomWalkOrRun();//随机走或跑
}
m_Agent.SetDestination(Camera.main.transform.position); //设置新的目的地
}
}
///
/// 炸弹爆炸
///
///
private void BombBrust(Vector3 brustPos)
{
if (Vector3.Distance(transform.position, brustPos) < 10.0f) //爆炸距离之内
{
BodyPartDrop[] drops = transform.GetComponentsInChildren();//查找子物体上的所有组件 数组
foreach (var item in drops)
{
item.Hit();
}
Death();
}
}
///
/// 死亡
///
public void Death()
{
if (m_IsDeath) return; //如果挂掉就返回 不用重复执行
PlayAnim(4, "Death", "DeathValue"); //4中随机死亡动画
m_Agent.isStopped = true; //停止寻路
m_IsDeath = true;
Destroy(m_Agent); //销毁寻路组件 不销毁的话可能悬在半空中
EventCenter.Broadcast(EventDefine.ZombieDeath);
}
///
/// 左边受伤
///
public void HitLeft()
{
m_Anim.SetTrigger("HitLeft");
m_Agent.isStopped = true;
m_Anim.SetTrigger("Idle");
m_IsHitting = true;
StartCoroutine(HitDealy()); //受伤之后有一定的延迟
}
///
/// 右边受伤
///
public void HitRight()
{
m_Anim.SetTrigger("HitRight");
m_Agent.isStopped = true;
m_Anim.SetTrigger("Idle");
m_IsHitting = true;
StartCoroutine(HitDealy());
}
///
/// 随机受伤动画
///
public void Hit()
{
PlayAnim(3, "Hit", "HitValue"); //3种随机动画
m_Agent.isStopped = true;
m_Anim.SetTrigger("Idle");
m_IsHitting = true;
StartCoroutine(HitDealy());
}
IEnumerator HitDealy()
{
yield return new WaitForSeconds(m_HitDealyTime);
m_Agent.isStopped = false;
m_IsHitting = false;
RandomWalkOrRun();
}
///
/// 攻击
///
private void Attack()
{
if (m_AudioSource.isPlaying == false)
{
m_AudioSource.clip = audio_Attack;
m_AudioSource.Play();
}
EventCenter.Broadcast(EventDefine.UpdateHP, -10); //广播减少血量事件
EventCenter.Broadcast(EventDefine.ScreenBlood);
Vector3 targetPos = new Vector3(m_Target.position.x, transform.position.y, m_Target.position.z);
transform.LookAt(targetPos);
PlayAnim(6, "Attack", "AttackValue"); //随机攻击动画片段
}
///
/// 随机播放跑或者走的动画
///
private void RandomWalkOrRun()
{
int ran = Random.Range(0, 2); //只随机0,1
if (ran == 0)
{
//走
WalkAnim();
m_Agent.speed = m_WalkSpeed;
}
else
{
//跑
RunAnim();
m_Agent.speed = m_RunSpeed;
}
}
///
/// 走路动画
///
private void WalkAnim()
{
if (m_AudioSource.isPlaying == false)
{
m_AudioSource.clip = audio_Walk;
m_AudioSource.Play();
}
PlayAnim(3, "Walk", "WalkValue");
}
///
/// 跑的动画
///
private void RunAnim()
{
PlayAnim(2, "Run", "RunValue");
}
///
/// 随机动画片段 走路3个 跑步2个 0.5f递增
///
///
///
///
private void PlayAnim(int clipCount, string triggerName, string floatName)
{
float rate = 1.0f / (clipCount - 1); //等于0.5 或者 1
m_Anim.SetTrigger(triggerName); //设置动画触发器
m_Anim.SetFloat(floatName, rate * Random.Range(0, clipCount)); //0.5*0、1、2 或 1*0、1
}
}
HandManger:
HandManger
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HighlightingSystem;
using VRTK;
public enum GrabObjectType
{
None,
Other,
Book,
Pistol,
Belt,
Magazine,
Bomb,
}
public enum HandAnimStateType
{
None,
Pistol,
}
///
/// 左右手管理类
///
public class HandManger : MonoBehaviour
{
///
/// 监听抓取按键按下的事件码
///
public EventDefine GrabEvent; //定义不同类型 监听左右手柄不同的事件
public EventDefine ShotEvent;
public EventDefine UseBombEvent;
public EventDefine UsePistolEvent;
public GameObject go_Bomb; //炸弹
public float m_ThrowMulitiple = 1f;
private Animator m_Anim; //动画
///
/// 是否可以抓取
///
private bool m_IsCanGrab = false;
///
/// 当前抓取的物体
///
public GameObject m_GrabObj = null;
public GrabObjectType m_GrabObjectType = GrabObjectType.None;
public StateModel[] m_StateModels;
[System.Serializable] //序列化
public class StateModel
{
public HandAnimStateType StateType;
public GameObject go;
}
///
/// 判断手是否触碰到可以抓取的物体
///
private bool m_IsTrigger = false;
///
/// 是否使用手枪
///
private bool m_IsUsePistol = false;
///
/// 是否使用炸弹
///
private bool m_IsUseBomb = false;
private VRTK_ControllerEvents controllerEvents;
private void Awake()
{
m_Anim = GetComponent();
controllerEvents = GetComponentInParent();
EventCenter.AddListener(GrabEvent, IsCanGrab);
EventCenter.AddListener(ShotEvent, Shot);
EventCenter.AddListener(UseBombEvent, UseBomb);
EventCenter.AddListener(UsePistolEvent, UsePistol);
}
private void OnDestroy()
{
EventCenter.RemoveListener(GrabEvent, IsCanGrab);
EventCenter.RemoveListener(ShotEvent, Shot);
EventCenter.RemoveListener(UseBombEvent, UseBomb);
EventCenter.RemoveListener(UsePistolEvent, UsePistol);
}
///
/// 射击
///
private void Shot()
{
if (m_Anim.GetInteger("State") != (int)HandAnimStateType.Pistol) return;
m_Anim.SetTrigger("Shot");
}
///
/// 是否可以抓取物体的监听方法
///
///
private void IsCanGrab(bool value)
{
if (value == false)
{
if (m_GrabObj != null && m_GrabObjectType == GrabObjectType.Bomb)
{
//代表拿的是炸弹
ThrowBomb();
}
}
//释放抓取的物体
if (value)
{
if (m_GrabObj != null)
{
if (m_GrabObjectType == GrabObjectType.Other)
{
m_GrabObj.transform.parent = null;
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
else if (m_GrabObjectType == GrabObjectType.Book)
{
if (m_GrabObj.GetComponent().m_IsTrigger)
{
m_GrabObj.GetComponent().Put();
}
else
{
m_GrabObj.transform.parent = null;
m_GrabObj.transform.position = m_GrabObj.GetComponent().m_StratPos;
m_GrabObj.transform.rotation = m_GrabObj.GetComponent().m_StartRot;
}
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
else if (m_GrabObjectType == GrabObjectType.Belt || m_GrabObjectType == GrabObjectType.Magazine)
{
m_GrabObj.transform.parent = null;
m_GrabObj.GetComponent().useGravity = true;
m_GrabObj.GetComponent().constraints = RigidbodyConstraints.None;
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
return;
}
}
if (m_GrabObj == null)
m_Anim.SetBool("Catch", value);
m_IsCanGrab = value;
PistolOrBombChangeHand();
}
///
/// 投掷炸弹
///
private void ThrowBomb()
{
//更新炸弹数量
AmmoManager.Instance.UpdateBomb();
m_GrabObj.transform.parent = null; //设置父物体为空
m_GrabObj.AddComponent();//添加刚体
m_Anim.SetBool("Catch", false);//播放动画
m_GrabObjectType = GrabObjectType.None; //抓取物体类型为空
Vector3 velocity = controllerEvents.GetVelocity(); //获取手柄速度
Vector3 angularVelocity = controllerEvents.GetAngularVelocity();//获取手柄角速度
m_GrabObj.GetComponent().velocity = transform.parent.parent.TransformDirection(velocity) * m_ThrowMulitiple;//速度
m_GrabObj.GetComponent().angularVelocity = transform.parent.parent.TransformDirection(angularVelocity); //角速度
m_GrabObj.GetComponent().IsThrow = true;//可以扔
m_GrabObj = null;
m_IsUseBomb = false;
UsePistol();//投掷玩之后切换成手枪
}
///
/// 手枪换手 炸弹换手
///
private void PistolOrBombChangeHand()
{
//1.满足当前手没有抓取任何物体
//2.当前手没有触碰到任何可以抓取的物体
//3.另外一只手要保证拿着枪
if (m_GrabObj == null && m_IsTrigger == false && m_IsCanGrab == false)
{
HandManger[] handMangers = GameObject.FindObjectsOfType();
foreach (var handManger in handMangers)
{
if (handManger != this)
{
//手枪换手
if (handManger.m_IsUsePistol)
{
UsePistol();
handManger.UnUsePistol();
m_StateModels[0].go.GetComponent().m_CurrentBulletCount =
handManger.m_StateModels[0].go.GetComponent().m_CurrentBulletCount; //手枪换手 子弹同步
}
//炸弹换手
if (handManger.m_IsUseBomb)
{
handManger.UnUseBomb();
UseBomb();
}
}
}
}
}
///
/// 抓取
/// 作用:一只手拿另外一种手的物体的一些逻辑处理
///
///
public void Catch(bool value)
{
if (m_GrabObj != null)
{
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
m_Anim.SetBool("Catch", value);
}
///
/// 使用炸弹
///
private void UseBomb()
{
if (AmmoManager.Instance.IsHasBomb() == false) return;
//判断当前右手是否拿着物品,如果拿着则卸掉
if (m_GrabObj != null)
{
if (m_GrabObjectType == GrabObjectType.Pistol)
{
UnUsePistol();
}
else if (m_GrabObjectType == GrabObjectType.Belt || m_GrabObjectType == GrabObjectType.Magazine)
{
m_GrabObj.transform.parent = null;
m_GrabObj.GetComponent().useGravity = true;
m_GrabObj.GetComponent().constraints = RigidbodyConstraints.None; //解除
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
else if (m_GrabObjectType == GrabObjectType.Bomb) //拿到炸弹就返回
{
return;
}
}
Transform target = transform.parent.Find("BombTarget"); //重置炸弹位置
GameObject bomb = Instantiate(go_Bomb, transform.parent);
bomb.transform.localPosition = target.localPosition;
bomb.transform.localRotation = target.localRotation;
bomb.transform.localScale = target.localScale;
m_GrabObj = bomb;
m_GrabObjectType = GrabObjectType.Bomb;
m_Anim.SetBool("Catch", true);
m_IsUseBomb = true;
}
///
/// 卸载炸弹
///
public void UnUseBomb()
{
m_IsUseBomb = false;
Destroy(m_GrabObj);
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
m_Anim.SetBool("Catch", false);
}
///
/// 使用手枪
///
private void UsePistol()
{
if (m_GrabObj != null)
{
if (m_GrabObjectType == GrabObjectType.Belt || m_GrabObjectType == GrabObjectType.Magazine)
{
m_GrabObj.transform.parent = null;
m_GrabObj.GetComponent().useGravity = true;
m_GrabObj.GetComponent().constraints = RigidbodyConstraints.None;
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
else if (m_GrabObjectType == GrabObjectType.Bomb)
{
UnUseBomb();
}
else if (m_GrabObjectType == GrabObjectType.Pistol)
{
return;
}
}
m_IsUsePistol = true;
m_Anim.SetBool("Catch", false);
m_GrabObjectType = GrabObjectType.Pistol;
m_GrabObj = m_StateModels[0].go;
//切换成拿枪的动画
//显示手枪
TurnState(HandAnimStateType.Pistol);
}
///
/// 卸下手枪
///
public void UnUsePistol()
{
m_IsUsePistol = false;
m_Anim.SetBool("Catch", false);
m_GrabObjectType = GrabObjectType.None;
m_GrabObj = null;
TurnState(HandAnimStateType.None);
}
private void TurnState(HandAnimStateType stateType)
{
m_Anim.SetInteger("State", (int)stateType);
foreach (var item in m_StateModels)
{
if (item.StateType == stateType && item.go.activeSelf == false)
{
item.go.SetActive(true);
}
else if (item.go.activeSelf)
{
item.go.SetActive(false);
}
}
}
private void OnTriggerStay(Collider other)
{
if (other.tag == "Others" || other.tag == "Book" || other.tag == "Pistol" || other.tag == "Belt" || other.tag == "Magazine")
{
m_IsTrigger = true;
}
if (other.GetComponent() != null) //开启高亮 红色 注意引入命名空间
{
other.GetComponent().On(Color.red);
}
if (other.tag == "Others" && m_IsCanGrab && m_GrabObj == null)
{
ProcessGrab(other);
m_GrabObjectType = GrabObjectType.Other; //抓取物体的类型
}
else if (other.tag == "Book" && m_IsCanGrab && m_GrabObj == null)
{
ProcessGrab(other);
m_GrabObjectType = GrabObjectType.Book; //抓取书
}
else if (other.tag == "Pistol" && m_IsCanGrab && m_GrabObj == null)
{
EventCenter.Broadcast(EventDefine.WearPistol);
Destroy(other.gameObject);
UsePistol();
}
else if (other.tag == "Belt" && m_IsCanGrab && m_GrabObj == null)
{
ProcessGrab(other);
other.GetComponent().useGravity = false;
other.GetComponent().constraints = RigidbodyConstraints.FreezeAll;
m_GrabObjectType = GrabObjectType.Belt;
}
else if (other.tag == "Magazine" && m_IsCanGrab && m_GrabObj == null)
{
ProcessGrab(other);
other.GetComponent().useGravity = false;
other.GetComponent().constraints = RigidbodyConstraints.FreezeAll;
m_GrabObjectType = GrabObjectType.Magazine;
}
}
///
/// 处理抓取
///
///
private void ProcessGrab(Collider other)
{
//一只手拿另外一种手的物体的一些逻辑处理
if (other.transform.parent != null)
{
if (other.transform.parent.tag == "ControllerRight" || other.transform.parent.tag == "ControllerLeft")
{
other.transform.parent.GetComponentInChildren().Catch(false);
}
}
Catch(true);
other.gameObject.transform.parent = transform.parent;
m_GrabObj = other.gameObject;
}
private void OnTriggerExit(Collider other)
{
if (other.GetComponent() != null)
{
other.GetComponent().Off(); //关闭高亮
}
m_IsTrigger = false;
}
}
UI:
AmmoManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
///
/// 弹药库的管理
///
public class AmmoManager : MonoBehaviour
{
public static AmmoManager Instance; //单例模式
///
/// 子弹数量
///
public int BulletCount;
///
/// 炸弹数量
///
public int BombCount;
private Transform target; //目标物体
private Text txt_Bullet;//子弹数量
private Text txt_Bomb;//炸弹数量
private void Awake()
{
Instance = this; //单例赋值
}
private void Start()
{
txt_Bullet = transform.Find("Bullet/Text").GetComponent();
txt_Bomb = transform.Find("Bomb/Text").GetComponent();
target = GameObject.FindGameObjectWithTag("CameraRig").transform; //查找目标物体
EventCenter.AddListener(EventDefine.WearBelt, Show); //监听穿戴事件
gameObject.SetActive(false); //默认隐藏
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.WearBelt, Show); //移除监听事件
}
///
/// 实时跟踪位置和旋转信息
///
private void FixedUpdate()
{
float height = target.GetComponent().height;
transform.position = new Vector3(Camera.main.transform.position.x, height, Camera.main.transform.position.z);
transform.eulerAngles = new Vector3(transform.eulerAngles.x, Camera.main.transform.eulerAngles.y, 0);
}
///
/// 显示弹药库界面
///
private void Show()
{
gameObject.SetActive(true); //显示界面
UpdateBullet(0);//执行更新子弹的函数
UpdateBomb(0);//执行更新炸弹的函数
}
///
/// 重装弹夹
///
public int ReloadMagazine()
{
if (BulletCount >= 6)
{
UpdateBullet(-6);
return 6;
}
else
{
int temp = BulletCount;
BulletCount = 0;
UpdateBullet(0);
return temp;
}
}
///
/// 是否有手榴弹
///
///
public bool IsHasBomb()
{
if (BombCount <= 0)
{
return false;
}
return true;
}
///
/// 更新子弹数量
///
///
public void UpdateBullet(int count)
{
BulletCount += count;
txt_Bullet.text = BulletCount.ToString();
}
///
/// 更新手榴弹数量
///
///
public void UpdateBomb(int count = -1)
{
BombCount += count;
txt_Bomb.text = BombCount.ToString();
}
}
Loading
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
///
/// 异步加载
///
public class Loading : MonoBehaviour
{
public string LoadSceneName;
private Text text;
private AsyncOperation m_Ao; //异步加载操作
private bool m_IsLoad = false;
private void Awake()
{
text = GetComponent();
gameObject.SetActive(false);
EventCenter.AddListener(EventDefine.StartLoadScene, StartLoadScene); //监听异步加载的事件
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.StartLoadScene, StartLoadScene); //移除监听事件
}
private void StartLoadScene()
{
gameObject.SetActive(true);
StartCoroutine("Load");//只有引号才能停止协程
}
IEnumerator Load()
{
int startProcess = -1;
int endProcess = 100;
while (startProcess < endProcess)
{
startProcess++;
Show(startProcess);
if (m_IsLoad == false)
{
m_Ao = SceneManager.LoadSceneAsync(LoadSceneName); //异步加载场景
m_Ao.allowSceneActivation = false;//先没有激活场景 加载完成后再激活
m_IsLoad = true;
}
yield return new WaitForEndOfFrame(); //等待加载完成
}
if (startProcess == 100)
{
m_Ao.allowSceneActivation = true;
StopCoroutine("Load");
}
}
private void Show(int value)
{
text.text = value.ToString() + "%";
}
}
RadialMenuManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 圆环控制器
///
public class RadialMenuManager : MonoBehaviour
{
private bool m_IsWearBelt = false;
private bool m_IsWearPistol = false;
private void Awake()
{
gameObject.SetActive(false); //默认圆环是隐藏的
EventCenter.AddListener(EventDefine.WearBelt, WearBelt); //监听手枪拿起和腰带佩戴上才可以 显示圆环
EventCenter.AddListener(EventDefine.WearPistol, WearPistol);
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.WearBelt, WearBelt);
EventCenter.RemoveListener(EventDefine.WearPistol, WearPistol);
}
///
/// 腰带穿戴上的监听方法
///
private void WearBelt()
{
m_IsWearBelt = true;
if (m_IsWearBelt && m_IsWearPistol)
{
gameObject.SetActive(true); //腰带和枪都带上才能显示圆环 在广播带上枪和腰带的方法 Belt 17 HandManger 357
}
}
///
/// 枪拿起的监听方法
///
private void WearPistol()
{
m_IsWearPistol = true;
if (m_IsWearBelt && m_IsWearPistol)
{
gameObject.SetActive(true);
}
}
///
/// 圆盘上点击手枪的函数
///
public void OnUsePistolClick()
{
HandManger handManger = transform.parent.parent.parent.GetComponentInChildren(); //获取手管理类 注意父级关系
if (handManger.m_GrabObj != null && handManger.m_GrabObjectType == GrabObjectType.Pistol) //判断手上握的是手枪 则卸载手枪
{
handManger.UnUsePistol();
}
if (handManger.m_GrabObj != null && handManger.m_GrabObjectType == GrabObjectType.Bomb) //握住炸弹则卸载炸弹
{
handManger.UnUseBomb();
}
EventCenter.Broadcast(EventDefine.UsePistol); //广播使用手枪的事件码
EventCenter.Broadcast(EventDefine.IsStartGestureRecognition, false);//广播使用手势的事件码 不可以使用
}
///
/// 圆盘上点击炸弹的函数
///
public void OnUseBombClick()
{
HandManger handManger = transform.parent.parent.parent.GetComponentInChildren(); //避免左手拿到手枪之后不能继续切换
if (handManger.m_GrabObj != null && handManger.m_GrabObjectType == GrabObjectType.Pistol)
{
handManger.UnUsePistol(); //卸载手枪
}
if (handManger.m_GrabObj != null && handManger.m_GrabObjectType == GrabObjectType.Bomb)
{
handManger.UnUseBomb();//卸载炸弹
}
EventCenter.Broadcast(EventDefine.UseBomb); //广播使用炸弹的事件码
EventCenter.Broadcast(EventDefine.IsStartGestureRecognition, false); //广播使用手势的事件码 不可使用
}
///
/// 圆盘上点击手势的按钮
///
public void OnUseGestureClick()
{
HandManger[] handMangers = GameObject.FindObjectsOfType(); //无论手上握住任何东西都卸载
foreach (var handManger in handMangers)
{
if (handManger.m_GrabObj != null && handManger.m_GrabObjectType == GrabObjectType.Pistol)
{
handManger.UnUsePistol(); //手上有枪则卸载
}
if (handManger.m_GrabObj != null && handManger.m_GrabObjectType == GrabObjectType.Bomb)
{
handManger.UnUseBomb();//手上有炸弹则卸载
}
}
EventCenter.Broadcast(EventDefine.IsStartGestureRecognition, true); //广播使用手势的事件码 可以使用手势 点击圆盘其他按钮的时候广播 不可用手势识别 false
}
}
Gesture:
BaseGestureRecognition
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Edwon.VR;
using Edwon.VR.Gesture;
///
/// 手势识别基类 抽象类
///
public abstract class BaseGestureRecognition : MonoBehaviour
{
private VRGestureSettings gestureSettings;
protected VRGestureRig gestureRig;
public abstract void OnGestureDetectedEvent(string gestureName, double confidence); //抽象的方法
public virtual void Awake() //虚方法 要重写
{
gestureSettings = Utils.GetGestureSettings();
gestureRig = VRGestureRig.GetPlayerRig(gestureSettings.playerID);
GestureRecognizer.GestureDetectedEvent += GestureRecognizer_GestureDetectedEvent; //监听事件 自动补全方法
}
public virtual void OnDestroy() //虚方法
{
GestureRecognizer.GestureDetectedEvent -= GestureRecognizer_GestureDetectedEvent;//移除监听
}
///
/// 当手势被检测到
///
///
///
///
///
private void GestureRecognizer_GestureDetectedEvent(string gestureName, double confidence, Handedness hand, bool isDouble = false) //手势名称 识别精度 左右手 是否双手
{
OnGestureDetectedEvent(gestureName, confidence);
}
///
/// 开始手势识别 受保护
///
protected void BeginRecognition()
{
gestureRig.BeginDetect();
}
}
GestureDetectedPanel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Edwon.VR;
using Edwon.VR.Gesture;
public class GestureDetectedPanel : BaseGestureRecognition
{
private Button btn_Back;
private Text txt_GestureName;
private Text txt_GestureConfidence;
public override void Awake()
{
base.Awake();
btn_Back = transform.Find("btn_Back").GetComponent
GestureEditPanel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Edwon.VR;
using Edwon.VR.Gesture;
public class GestureEditPanel : MonoBehaviour
{
public GameObject go_GestureExampleItem;
public Material m_Mat;
private Text txt_GestureName;
private Button btn_Back;
private Button btn_Record;
private VRGestureSettings gestureSettings;
private VRGestureRig gestureRig;
///
/// 手势所对应的所有的手势记录list
///
private List gestureExamples = new List();
private List exampleObjList = new List();
///
/// 手势名字
///
private string m_GestureName;
///
/// 判断是否开始录制
///
private bool m_IsStartRecord = false;
private void Awake()
{
gestureSettings = Utils.GetGestureSettings();
gestureRig = VRGestureRig.GetPlayerRig(gestureSettings.playerID);
EventCenter.AddListener(EventDefine.ShowGestureEditPanel, Show);
EventCenter.AddListener(EventDefine.FinishedOnceRecord, FinishedOnceRecord);
EventCenter.AddListener(EventDefine.UIPointHovering, UIPointHovering);
Init();
}
private void Init()
{
txt_GestureName = transform.Find("txt_GestureName").GetComponent();
btn_Back = transform.Find("btn_Back").GetComponent
GestureMainPanel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Edwon.VR;
using Edwon.VR.Gesture;
///
/// 手势识别
///
public class GestureMainPanel : MonoBehaviour
{
private Button btn_GestureInfo;
private Button btn_GestureDetect;
private VRGestureSettings gestureSettings;
private VRGestureRig gestureRig;
private void Awake()
{
gestureSettings = Utils.GetGestureSettings();//赋值
gestureRig = VRGestureRig.GetPlayerRig(gestureSettings.playerID);
btn_GestureInfo = transform.Find("btn_GestureInfo").GetComponent();
btn_GestureInfo.onClick.AddListener(() => //手势按钮点击事件设置
{
//进入手势信息页面
EventCenter.Broadcast(EventDefine.ShowGestureInfoPanel);
gameObject.SetActive(false);
});
btn_GestureDetect = transform.Find("btn_GestureDetect").GetComponent();
btn_GestureDetect.onClick.AddListener(() =>
{
//进入手势测试界面
EventCenter.Broadcast(EventDefine.ShowGextureDetectedPanel);
gameObject.SetActive(false);
});
EventCenter.AddListener(EventDefine.ShowGestureMainPanel, Show);
Show();
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.ShowGestureMainPanel, Show);
}
private void Show()
{
gestureRig.uiState = VRGestureUIState.Idle;
gameObject.SetActive(true);
}
}
SkillChoosePanel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SkillChoosePanel : MonoBehaviour
{
private string m_GestureName;
private void Awake()
{
EventCenter.AddListener(EventDefine.ShowSkillChoosePanel, Show);
Init();
}
private void Init()
{
transform.Find("btn_Back").GetComponent().onClick.AddListener(() =>
{
//更换技能
for (int i = 0; i < transform.Find("Parent").childCount; i++)
{
if (transform.Find("Parent").GetChild(i).GetComponent().isOn)
{
GestureSkillManager.ChangeSkill(m_GestureName, transform.Find("Parent").GetChild(i).name); //获取名字
}
}
EventCenter.Broadcast(EventDefine.ShowGestureInfoPanel); //注意顺序
gameObject.SetActive(false);
});
gameObject.SetActive(false);
}
private void OnDestroy()
{
//EventCenter.AddListener(EventDefine.ShowSkillChoosePanel, Show);
EventCenter.RemoveListener(EventDefine.ShowSkillChoosePanel, Show);
}
private void Update()
{
for (int i = 0; i < transform.Find("Parent").childCount; i++)
{
if (transform.Find("Parent").GetChild(i).GetComponent().isOn)
{
transform.Find("Parent").GetChild(i).GetChild(0).gameObject.SetActive(true);
}
else
{
transform.Find("Parent").GetChild(i).GetChild(0).gameObject.SetActive(false);
}
}
}
private void Show(string gestureName)
{
gameObject.SetActive(true);
m_GestureName = gestureName;
string skillName = GestureSkillManager.GetSkillNameByGestureName(gestureName);
for (int i = 0; i < transform.Find("Parent").childCount; i++)
{
if (transform.Find("Parent").GetChild(i).name == skillName)
{
transform.Find("Parent").GetChild(i).GetComponent().isOn = true;
transform.Find("Parent").GetChild(i).GetChild(0).gameObject.SetActive(true);
}
else
{
transform.Find("Parent").GetChild(i).GetComponent().isOn = false;
transform.Find("Parent").GetChild(i).GetChild(0).gameObject.SetActive(false);
}
}
}
}