一、框架視圖
二刺下、主要代碼
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<VRTK_ControllerEvents>();
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;
/// <summary>
/// 受傷后掉落
/// </summary>
public class BodyPartDrop : MonoBehaviour
{
public GameObject go_Firend;
public void SetFriend(GameObject go)
{
go_Firend = go;
}
/// <summary>
/// 受傷后掉落的處理
/// </summary>
public void Hit()
{
BodyPartDrop[] arr = transform.parent.GetComponentsInChildren<BodyPartDrop>();
foreach (var item in arr) //中間掉落 下面也要跟著掉落
{
item.go_Firend.SetActive(false);
item.transform.parent = null;
item.transform.GetChild(0).gameObject.SetActive(true);
item.gameObject.AddComponent<Rigidbody>();
Destroy(item);
}
}
}
Bomb
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 爆炸
/// </summary>
public class Bomb : MonoBehaviour
{
public bool IsThrow = false; //是都可以投擲
public float BrustTime = 5f; //爆炸等待時(shí)間
public GameObject effect_Brust; //爆炸特效
private float m_Timer = 0.0f; //計(jì)時(shí)器
private void FixedUpdate()
{
if (IsThrow) //判斷是否可以爆炸 在手管理類的時(shí)候投擲炸彈設(shè)置為true HandManger170
{
m_Timer += Time.deltaTime;
if (m_Timer >= BrustTime)
{
Instantiate(effect_Brust, transform.position, transform.rotation); //實(shí)例化特效
Destroy(gameObject);
EventCenter.Broadcast(EventDefine.BombBrust, transform.position);//廣播發(fā)生爆炸特效的事件 當(dāng)前爆炸位置的信息
}
}
}
}
Book
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum BookType
{
StartBook,
AboutBook,
GestureBook
}
/// <summary>
/// 書籍管理類
/// </summary>
public class Book : MonoBehaviour
{
public BookType m_BookType;
public Vector3 m_StratPos;
public Quaternion m_StartRot;
/// <summary>
/// 判斷書本是否觸發(fā)到書臺(tái)
/// </summary>
public bool m_IsTrigger = false;
/// <summary>
/// 觸發(fā)的書臺(tái)物體
/// </summary>
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);
}
}
}
/// <summary>
/// 放置書本
/// </summary>
public void Put()
{
if (go_StandBook.GetComponentInChildren<Book>() != null)
{
go_StandBook.GetComponentInChildren<Book>().Release();
}
transform.parent = go_StandBook.transform;
transform.position = go_StandBook.transform.GetChild(0).position;
transform.rotation = go_StandBook.transform.GetChild(0).rotation;
IsActiveUI(true);
}
/// <summary>
/// 書本歸為
/// </summary>
public void Release()
{
transform.parent = null;
transform.position = m_StratPos;
transform.rotation = m_StartRot;
IsActiveUI(false);
}
/// <summary>
/// 是否激活當(dāng)前書本對應(yīng)的UI界面
/// </summary>
/// <param name="value"></param>
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;
/// <summary>
/// 檢測手勢
/// </summary>
public class GestureRecognition : BaseGestureRecognition
{
public override void Awake()
{
base.Awake();
EventCenter.AddListener<bool>(EventDefine.IsStartGestureRecognition, IsStartGestureRecognition); //后面可以是方法或者直接賦值 布爾變量
}
public override void OnDestroy()
{
base.OnDestroy();
EventCenter.RemoveListener<bool>(EventDefine.IsStartGestureRecognition, IsStartGestureRecognition);
}
/// <summary>
/// 是否開始手勢識別
/// </summary>
/// <param name="value"></param>
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); //加載技能預(yù)制體
Instantiate(skill, new Vector3(Camera.main.transform.position.x, 0, Camera.main.transform.position.z), skill.transform.rotation); //實(shí)例化技能 注意生成的位置
}
}
GestureSkillManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Edwon.VR;
using Edwon.VR.Gesture;
/// <summary>
/// 手勢技能管理
/// </summary>
public class GestureSkillManager
{
/// <summary>
/// 手勢名與技能名的字典
/// </summary>
private static Dictionary<string, string> m_GestureSkillDic = new Dictionary<string, string>();
private static VRGestureSettings gestureSettings;
private static string SkillName = "Skill";
static GestureSkillManager()
{
gestureSettings = Utils.GetGestureSettings();
m_GestureSkillDic = GetGestureSkillDic();
}
/// <summary>
/// 獲取手勢名與技能名之間的關(guān)系
/// </summary>
/// <returns></returns>
private static Dictionary<string, string> GetGestureSkillDic()
{
Dictionary<string, string> gestureSkillDic = new Dictionary<string, string>();
//規(guī)則:手勢名-技能名绑嘹;手勢名-技能名
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;
}
/// <summary>
/// 保存手勢與技能之間的關(guān)系
/// </summary>
private static void SaveGestureSkillDic(Dictionary<string, string> dic)
{
string temp = "";
int index = 0;
foreach (var item in dic)
{
//規(guī)則:手勢名-技能名;手勢名-技能名
temp += item.Key + "-" + item.Value;
index++;
if (index != dic.Count)
temp += ";";
}
PlayerPrefs.SetString("GestureSkill", temp);
}
/// <summary>
/// 通過手勢名獲取技能名
/// </summary>
public static string GetSkillNameByGestureName(string gestureName)
{
if (m_GestureSkillDic.ContainsKey(gestureName))
{
return m_GestureSkillDic[gestureName];
}
return null;
}
/// <summary>
/// 更換手勢與技能之間的關(guān)系(更換技能)
/// </summary>
/// <param name="gestureName"></param>
/// <param name="newSkillName"></param>
public static void ChangeSkill(string gestureName, string newSkillName)
{
if (m_GestureSkillDic.ContainsKey(gestureName))
{
m_GestureSkillDic[gestureName] = newSkillName;
SaveGestureSkillDic(m_GestureSkillDic);
}
}
/// <summary>
/// 通過手勢名獲取技能圖片
/// </summary>
/// <param name="gestureName"></param>
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;
/// <summary>
/// 血量管理類
/// </summary>
public class HPManager : MonoBehaviour
{
public int HP = 10000;
private void Awake()
{
EventCenter.AddListener<int>(EventDefine.UpdateHP, UpdateHP);
EventCenter.AddListener<Vector3>(EventDefine.BombBrust, BombBrust);
}
private void OnDestroy()
{
EventCenter.RemoveListener<int>(EventDefine.UpdateHP, UpdateHP);
EventCenter.RemoveListener<Vector3>(EventDefine.BombBrust, BombBrust);
}
/// <summary>
/// 炸彈爆炸
/// </summary>
/// <param name="brustPos"></param>
private void BombBrust(Vector3 brustPos)
{
if (Vector3.Distance(transform.position, brustPos) < 10.0f)
{
UpdateHP(-20);
}
}
/// <summary>
/// 更新血量
/// </summary>
/// <param name="count"></param>
private void UpdateHP(int count)
{
if (count < 0)
{
if (HP <= Mathf.Abs(count))//血量小于0 掛掉
{
//死亡
HP = 0;
Death(); //加載當(dāng)前活躍的場景
}
else
{
HP += count; //增加血量
}
}
else
{
HP += count;
}
EventCenter.Broadcast(EventDefine.UpdateHpUI, HP); //廣播更新血量的事件碼
}
private void Death()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); //加載當(dāng)前場景
}
}
Magazine
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 彈夾管理類
/// </summary>
public class Magazine : MonoBehaviour
{
/// <summary>
/// 子彈數(shù)量
/// </summary>
private int BulletCount = 6;
/// <summary>
/// 設(shè)置子彈的方法
/// </summary>
/// <param name="count"></param>
public void SetBulletCount(int count)
{
BulletCount = count;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Backet")
{
if (transform.parent != null && transform.parent.GetComponentInChildren<HandManger>() != null)
{
Destroy(gameObject);
transform.parent.GetComponentInChildren<HandManger>().Catch(false);
//加子彈
AmmoManager.Instance.UpdateBullet(BulletCount);
}
}
}
}
Pistol
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 手槍
/// </summary>
public class Pistol : MonoBehaviour
{
public EventDefine ShotEvent;//射擊事件 這兩個(gè)要在面板上指定是哪個(gè)事件 分別是左右手
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;//動(dòng)畫
private RaycastHit m_Hit;//射線
public int m_CurrentBulletCount = 6; //彈夾數(shù)量
private AudioSource m_AudioSource;
private void Awake()
{
m_AudioSource = GetComponent<AudioSource>(); //獲取組件
m_LineRenderer = GetComponent<LineRenderer>();
m_Anim = GetComponent<Animator>();
EventCenter.AddListener(ShotEvent, Shot);//添加射擊監(jiān)聽 廣播事件是分別執(zhí)行左右手
EventCenter.AddListener(ReloadMagazineEvent, ReloadMagazine);//添加換彈夾事件 廣播時(shí)候左右手按下圓盤時(shí)候
}
private void OnDestroy()
{
EventCenter.RemoveListener(ShotEvent, Shot);//移除監(jiān)聽射擊事件
EventCenter.RemoveListener(ReloadMagazineEvent, ReloadMagazine); //移除換彈夾事件
}
/// <summary>
/// 換彈夾
/// </summary>
private void ReloadMagazine()
{
//代表是Main場景 則忽略
if (SceneManager.GetActiveScene().buildIndex == 0) return;
//如果手槍是隱藏的橘茉,則忽略
if (gameObject.activeSelf == false) return;
//如果當(dāng)前正在播放開火的動(dòng)畫工腋,則忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Fire")) return;
//如果當(dāng)前正在播放換彈夾的動(dòng)畫蛤克,則忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Reload")) return;
if (GameObject.FindObjectOfType<RadialMenuManager>() != null)
if (GameObject.FindObjectOfType<RadialMenuManager>().transform.localScale != Vector3.zero)
return;
int temp = m_CurrentBulletCount; //當(dāng)前數(shù)量
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<Magazine>().SetBulletCount(temp);
}
}
/// <summary>
/// 射擊
/// </summary>
private void Shot()
{
//代表是Main場景 則忽略
if (SceneManager.GetActiveScene().buildIndex == 0) return;
//如果手槍是隱藏的,則忽略
if (gameObject.activeSelf == false) return;
//如果當(dāng)前正在播放開火的動(dòng)畫夷蚊,則忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Fire")) return;
//如果當(dāng)前正在播放換彈夾的動(dòng)畫夭苗,則忽略
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("Reload")) return;
if (m_CurrentBulletCount <= 0) return;
m_CurrentBulletCount--; //子彈數(shù)量減減
//播放射擊動(dòng)畫
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<BodyPartDrop>() != null)
{
m_Hit.transform.GetComponent<BodyPartDrop>().Hit();
}
if (m_Hit.transform.GetComponent<ZombieHit>() != null)
{
m_Hit.transform.GetComponent<ZombieHit>().Hit();
}
//實(shí)例化血的特效添瓷,1.5秒之后銷毀
Destroy(Instantiate(effect_Blood, m_Hit.point, Quaternion.LookRotation(m_Hit.normal)), 2f); //旋轉(zhuǎn)看向受傷的地方
}
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);//實(shí)例化煙霧 2秒后消失
}
}
}
/// <summary>
/// 畫線
/// </summary>
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;
/// <summary>
/// 控制器
/// </summary>
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; //受傷延遲
/// <summary>
/// 攻擊時(shí)間間隔
/// </summary>
public float m_AttackInterval = 3f;
public AudioClip audio_Attack;
public AudioClip audio_Walk;
private NavMeshAgent m_Agent; //導(dǎo)航網(wǎng)格
private Animator m_Anim;
private Transform m_Target; //相機(jī)位置
/// <summary>
/// 是否第一次攻擊
/// </summary>
private bool m_IsFirstAttack = true;
private float m_Timer = 0.0f;
/// <summary>
/// 是否正在攻擊
/// </summary>
private bool m_IsAttacking = false;
/// <summary>
/// 是否正在受傷中
/// </summary>
private bool m_IsHitting = false;
/// <summary>
/// 僵尸是否死亡
/// </summary>
private bool m_IsDeath = false;
public bool IsDeath
{
get
{
return m_IsDeath;
}
}
private AudioSource m_AudioSource; //聲效
private void Awake()
{
m_AudioSource = GetComponent<AudioSource>();
m_Anim = GetComponent<Animator>();
m_Agent = GetComponent<NavMeshAgent>();
m_Target = Camera.main.transform; //相機(jī)信息
EventCenter.AddListener<Vector3>(EventDefine.BombBrust, BombBrust); //監(jiān)聽炸彈爆炸的事件碼
}
private void OnDestroy()
{
EventCenter.RemoveListener<Vector3>(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) //判斷相機(jī)跟物體之間的距離
{
if (m_Agent.isStopped == false)
{
m_Agent.isStopped = true; //停止導(dǎo)航
}
if (m_IsAttacking == false)
{
m_Timer += Time.deltaTime;
if (m_Timer >= m_AttackInterval)
{
m_Timer = 0.0f;
m_IsAttacking = true; //調(diào)用攻擊的函數(shù)
Attack();
}
}
if (m_Anim.GetCurrentAnimatorStateInfo(0).IsName("AttackBlendTree") == false) //第0層的播放動(dòng)畫名稱
{
if (m_IsFirstAttack) //標(biāo)志位 只加一次0.5f 之后不加 避免判斷距離越來越大
{
m_DistanceJudge += 0.5f; //避免根據(jù)距離動(dòng)畫來回播放
m_IsFirstAttack = false;
m_IsAttacking = true;
Attack();
}
else
{
m_IsAttacking = false;
}
}
}
else
{ //沒達(dá)到距離 繼續(xù)尋路
if (m_Agent.isStopped)
{
m_DistanceJudge -= 0.5f; //避免根據(jù)距離動(dòng)畫來回播放
m_Agent.isStopped = false; //繼續(xù)尋路
m_IsFirstAttack = true;
RandomWalkOrRun();//隨機(jī)走或跑
}
m_Agent.SetDestination(Camera.main.transform.position); //設(shè)置新的目的地
}
}
/// <summary>
/// 炸彈爆炸
/// </summary>
/// <param name="brustPos"></param>
private void BombBrust(Vector3 brustPos)
{
if (Vector3.Distance(transform.position, brustPos) < 10.0f) //爆炸距離之內(nèi)
{
BodyPartDrop[] drops = transform.GetComponentsInChildren<BodyPartDrop>();//查找子物體上的所有組件 數(shù)組
foreach (var item in drops)
{
item.Hit();
}
Death();
}
}
/// <summary>
/// 死亡
/// </summary>
public void Death()
{
if (m_IsDeath) return; //如果掛掉就返回 不用重復(fù)執(zhí)行
PlayAnim(4, "Death", "DeathValue"); //4中隨機(jī)死亡動(dòng)畫
m_Agent.isStopped = true; //停止尋路
m_IsDeath = true;
Destroy(m_Agent); //銷毀尋路組件 不銷毀的話可能懸在半空中
EventCenter.Broadcast(EventDefine.ZombieDeath);
}
/// <summary>
/// 左邊受傷
/// </summary>
public void HitLeft()
{
m_Anim.SetTrigger("HitLeft");
m_Agent.isStopped = true;
m_Anim.SetTrigger("Idle");
m_IsHitting = true;
StartCoroutine(HitDealy()); //受傷之后有一定的延遲
}
/// <summary>
/// 右邊受傷
/// </summary>
public void HitRight()
{
m_Anim.SetTrigger("HitRight");
m_Agent.isStopped = true;
m_Anim.SetTrigger("Idle");
m_IsHitting = true;
StartCoroutine(HitDealy());
}
/// <summary>
/// 隨機(jī)受傷動(dòng)畫
/// </summary>
public void Hit()
{
PlayAnim(3, "Hit", "HitValue"); //3種隨機(jī)動(dòng)畫
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();
}
/// <summary>
/// 攻擊
/// </summary>
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"); //隨機(jī)攻擊動(dòng)畫片段
}
/// <summary>
/// 隨機(jī)播放跑或者走的動(dòng)畫
/// </summary>
private void RandomWalkOrRun()
{
int ran = Random.Range(0, 2); //只隨機(jī)0,1
if (ran == 0)
{
//走
WalkAnim();
m_Agent.speed = m_WalkSpeed;
}
else
{
//跑
RunAnim();
m_Agent.speed = m_RunSpeed;
}
}
/// <summary>
/// 走路動(dòng)畫
/// </summary>
private void WalkAnim()
{
if (m_AudioSource.isPlaying == false)
{
m_AudioSource.clip = audio_Walk;
m_AudioSource.Play();
}
PlayAnim(3, "Walk", "WalkValue");
}
/// <summary>
/// 跑的動(dòng)畫
/// </summary>
private void RunAnim()
{
PlayAnim(2, "Run", "RunValue");
}
/// <summary>
/// 隨機(jī)動(dòng)畫片段 走路3個(gè) 跑步2個(gè) 0.5f遞增
/// </summary>
/// <param name="clipCount"></param>
/// <param name="triggerName"></param>
/// <param name="floatName"></param>
private void PlayAnim(int clipCount, string triggerName, string floatName)
{
float rate = 1.0f / (clipCount - 1); //等于0.5 或者 1
m_Anim.SetTrigger(triggerName); //設(shè)置動(dòng)畫觸發(fā)器
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,
}
/// <summary>
/// 左右手管理類
/// </summary>
public class HandManger : MonoBehaviour
{
/// <summary>
/// 監(jiān)聽抓取按鍵按下的事件碼
/// </summary>
public EventDefine GrabEvent; //定義不同類型 監(jiān)聽左右手柄不同的事件
public EventDefine ShotEvent;
public EventDefine UseBombEvent;
public EventDefine UsePistolEvent;
public GameObject go_Bomb; //炸彈
public float m_ThrowMulitiple = 1f;
private Animator m_Anim; //動(dòng)畫
/// <summary>
/// 是否可以抓取
/// </summary>
private bool m_IsCanGrab = false;
/// <summary>
/// 當(dāng)前抓取的物體
/// </summary>
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;
}
/// <summary>
/// 判斷手是否觸碰到可以抓取的物體
/// </summary>
private bool m_IsTrigger = false;
/// <summary>
/// 是否使用手槍
/// </summary>
private bool m_IsUsePistol = false;
/// <summary>
/// 是否使用炸彈
/// </summary>
private bool m_IsUseBomb = false;
private VRTK_ControllerEvents controllerEvents;
private void Awake()
{
m_Anim = GetComponent<Animator>();
controllerEvents = GetComponentInParent<VRTK_ControllerEvents>();
EventCenter.AddListener<bool>(GrabEvent, IsCanGrab);
EventCenter.AddListener(ShotEvent, Shot);
EventCenter.AddListener(UseBombEvent, UseBomb);
EventCenter.AddListener(UsePistolEvent, UsePistol);
}
private void OnDestroy()
{
EventCenter.RemoveListener<bool>(GrabEvent, IsCanGrab);
EventCenter.RemoveListener(ShotEvent, Shot);
EventCenter.RemoveListener(UseBombEvent, UseBomb);
EventCenter.RemoveListener(UsePistolEvent, UsePistol);
}
/// <summary>
/// 射擊
/// </summary>
private void Shot()
{
if (m_Anim.GetInteger("State") != (int)HandAnimStateType.Pistol) return;
m_Anim.SetTrigger("Shot");
}
/// <summary>
/// 是否可以抓取物體的監(jiān)聽方法
/// </summary>
/// <param name="value"></param>
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<Book>().m_IsTrigger)
{
m_GrabObj.GetComponent<Book>().Put();
}
else
{
m_GrabObj.transform.parent = null;
m_GrabObj.transform.position = m_GrabObj.GetComponent<Book>().m_StratPos;
m_GrabObj.transform.rotation = m_GrabObj.GetComponent<Book>().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<Rigidbody>().useGravity = true;
m_GrabObj.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
return;
}
}
if (m_GrabObj == null)
m_Anim.SetBool("Catch", value);
m_IsCanGrab = value;
PistolOrBombChangeHand();
}
/// <summary>
/// 投擲炸彈
/// </summary>
private void ThrowBomb()
{
//更新炸彈數(shù)量
AmmoManager.Instance.UpdateBomb();
m_GrabObj.transform.parent = null; //設(shè)置父物體為空
m_GrabObj.AddComponent<Rigidbody>();//添加剛體
m_Anim.SetBool("Catch", false);//播放動(dòng)畫
m_GrabObjectType = GrabObjectType.None; //抓取物體類型為空
Vector3 velocity = controllerEvents.GetVelocity(); //獲取手柄速度
Vector3 angularVelocity = controllerEvents.GetAngularVelocity();//獲取手柄角速度
m_GrabObj.GetComponent<Rigidbody>().velocity = transform.parent.parent.TransformDirection(velocity) * m_ThrowMulitiple;//速度
m_GrabObj.GetComponent<Rigidbody>().angularVelocity = transform.parent.parent.TransformDirection(angularVelocity); //角速度
m_GrabObj.GetComponent<Bomb>().IsThrow = true;//可以扔
m_GrabObj = null;
m_IsUseBomb = false;
UsePistol();//投擲玩之后切換成手槍
}
/// <summary>
/// 手槍換手 炸彈換手
/// </summary>
private void PistolOrBombChangeHand()
{
//1.滿足當(dāng)前手沒有抓取任何物體
//2.當(dāng)前手沒有觸碰到任何可以抓取的物體
//3.另外一只手要保證拿著槍
if (m_GrabObj == null && m_IsTrigger == false && m_IsCanGrab == false)
{
HandManger[] handMangers = GameObject.FindObjectsOfType<HandManger>();
foreach (var handManger in handMangers)
{
if (handManger != this)
{
//手槍換手
if (handManger.m_IsUsePistol)
{
UsePistol();
handManger.UnUsePistol();
m_StateModels[0].go.GetComponent<Pistol>().m_CurrentBulletCount =
handManger.m_StateModels[0].go.GetComponent<Pistol>().m_CurrentBulletCount; //手槍換手 子彈同步
}
//炸彈換手
if (handManger.m_IsUseBomb)
{
handManger.UnUseBomb();
UseBomb();
}
}
}
}
}
/// <summary>
/// 抓取
/// 作用:一只手拿另外一種手的物體的一些邏輯處理
/// </summary>
/// <param name="value"></param>
public void Catch(bool value)
{
if (m_GrabObj != null)
{
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
}
m_Anim.SetBool("Catch", value);
}
/// <summary>
/// 使用炸彈
/// </summary>
private void UseBomb()
{
if (AmmoManager.Instance.IsHasBomb() == false) return;
//判斷當(dāng)前右手是否拿著物品彤枢,如果拿著則卸掉
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<Rigidbody>().useGravity = true;
m_GrabObj.GetComponent<Rigidbody>().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;
}
/// <summary>
/// 卸載炸彈
/// </summary>
public void UnUseBomb()
{
m_IsUseBomb = false;
Destroy(m_GrabObj);
m_GrabObj = null;
m_GrabObjectType = GrabObjectType.None;
m_Anim.SetBool("Catch", false);
}
/// <summary>
/// 使用手槍
/// </summary>
private void UsePistol()
{
if (m_GrabObj != null)
{
if (m_GrabObjectType == GrabObjectType.Belt || m_GrabObjectType == GrabObjectType.Magazine)
{
m_GrabObj.transform.parent = null;
m_GrabObj.GetComponent<Rigidbody>().useGravity = true;
m_GrabObj.GetComponent<Rigidbody>().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;
//切換成拿槍的動(dòng)畫
//顯示手槍
TurnState(HandAnimStateType.Pistol);
}
/// <summary>
/// 卸下手槍
/// </summary>
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<Highlighter>() != null) //開啟高亮 紅色 注意引入命名空間
{
other.GetComponent<Highlighter>().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<Rigidbody>().useGravity = false;
other.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
m_GrabObjectType = GrabObjectType.Belt;
}
else if (other.tag == "Magazine" && m_IsCanGrab && m_GrabObj == null)
{
ProcessGrab(other);
other.GetComponent<Rigidbody>().useGravity = false;
other.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
m_GrabObjectType = GrabObjectType.Magazine;
}
}
/// <summary>
/// 處理抓取
/// </summary>
/// <param name="other"></param>
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<HandManger>().Catch(false);
}
}
Catch(true);
other.gameObject.transform.parent = transform.parent;
m_GrabObj = other.gameObject;
}
private void OnTriggerExit(Collider other)
{
if (other.GetComponent<Highlighter>() != null)
{
other.GetComponent<Highlighter>().Off(); //關(guān)閉高亮
}
m_IsTrigger = false;
}
}
UI:
AmmoManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 彈藥庫的管理
/// </summary>
public class AmmoManager : MonoBehaviour
{
public static AmmoManager Instance; //單例模式
/// <summary>
/// 子彈數(shù)量
/// </summary>
public int BulletCount;
/// <summary>
/// 炸彈數(shù)量
/// </summary>
public int BombCount;
private Transform target; //目標(biāo)物體
private Text txt_Bullet;//子彈數(shù)量
private Text txt_Bomb;//炸彈數(shù)量
private void Awake()
{
Instance = this; //單例賦值
}
private void Start()
{
txt_Bullet = transform.Find("Bullet/Text").GetComponent<Text>();
txt_Bomb = transform.Find("Bomb/Text").GetComponent<Text>();
target = GameObject.FindGameObjectWithTag("CameraRig").transform; //查找目標(biāo)物體
EventCenter.AddListener(EventDefine.WearBelt, Show); //監(jiān)聽穿戴事件
gameObject.SetActive(false); //默認(rèn)隱藏
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.WearBelt, Show); //移除監(jiān)聽事件
}
/// <summary>
/// 實(shí)時(shí)跟蹤位置和旋轉(zhuǎn)信息
/// </summary>
private void FixedUpdate()
{
float height = target.GetComponent<CapsuleCollider>().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);
}
/// <summary>
/// 顯示彈藥庫界面
/// </summary>
private void Show()
{
gameObject.SetActive(true); //顯示界面
UpdateBullet(0);//執(zhí)行更新子彈的函數(shù)
UpdateBomb(0);//執(zhí)行更新炸彈的函數(shù)
}
/// <summary>
/// 重裝彈夾
/// </summary>
public int ReloadMagazine()
{
if (BulletCount >= 6)
{
UpdateBullet(-6);
return 6;
}
else
{
int temp = BulletCount;
BulletCount = 0;
UpdateBullet(0);
return temp;
}
}
/// <summary>
/// 是否有手榴彈
/// </summary>
/// <returns></returns>
public bool IsHasBomb()
{
if (BombCount <= 0)
{
return false;
}
return true;
}
/// <summary>
/// 更新子彈數(shù)量
/// </summary>
/// <param name="count"></param>
public void UpdateBullet(int count)
{
BulletCount += count;
txt_Bullet.text = BulletCount.ToString();
}
/// <summary>
/// 更新手榴彈數(shù)量
/// </summary>
/// <param name="count"></param>
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;
/// <summary>
/// 異步加載
/// </summary>
public class Loading : MonoBehaviour
{
public string LoadSceneName;
private Text text;
private AsyncOperation m_Ao; //異步加載操作
private bool m_IsLoad = false;
private void Awake()
{
text = GetComponent<Text>();
gameObject.SetActive(false);
EventCenter.AddListener(EventDefine.StartLoadScene, StartLoadScene); //監(jiān)聽異步加載的事件
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.StartLoadScene, StartLoadScene); //移除監(jiān)聽事件
}
private void StartLoadScene()
{
gameObject.SetActive(true);
StartCoroutine("Load");//只有引號才能停止協(xié)程
}
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;
/// <summary>
/// 圓環(huán)控制器
/// </summary>
public class RadialMenuManager : MonoBehaviour
{
private bool m_IsWearBelt = false;
private bool m_IsWearPistol = false;
private void Awake()
{
gameObject.SetActive(false); //默認(rèn)圓環(huán)是隱藏的
EventCenter.AddListener(EventDefine.WearBelt, WearBelt); //監(jiān)聽手槍拿起和腰帶佩戴上才可以 顯示圓環(huán)
EventCenter.AddListener(EventDefine.WearPistol, WearPistol);
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventDefine.WearBelt, WearBelt);
EventCenter.RemoveListener(EventDefine.WearPistol, WearPistol);
}
/// <summary>
/// 腰帶穿戴上的監(jiān)聽方法
/// </summary>
private void WearBelt()
{
m_IsWearBelt = true;
if (m_IsWearBelt && m_IsWearPistol)
{
gameObject.SetActive(true); //腰帶和槍都帶上才能顯示圓環(huán) 在廣播帶上槍和腰帶的方法 Belt 17 HandManger 357
}
}
/// <summary>
/// 槍拿起的監(jiān)聽方法
/// </summary>
private void WearPistol()
{
m_IsWearPistol = true;
if (m_IsWearBelt && m_IsWearPistol)
{
gameObject.SetActive(true);
}
}
/// <summary>
/// 圓盤上點(diǎn)擊手槍的函數(shù)
/// </summary>
public void OnUsePistolClick()
{
HandManger handManger = transform.parent.parent.parent.GetComponentInChildren<HandManger>(); //獲取手管理類 注意父級關(guān)系
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);//廣播使用手勢的事件碼 不可以使用
}
/// <summary>
/// 圓盤上點(diǎn)擊炸彈的函數(shù)
/// </summary>
public void OnUseBombClick()
{
HandManger handManger = transform.parent.parent.parent.GetComponentInChildren<HandManger>(); //避免左手拿到手槍之后不能繼續(xù)切換
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); //廣播使用手勢的事件碼 不可使用
}
/// <summary>
/// 圓盤上點(diǎn)擊手勢的按鈕
/// </summary>
public void OnUseGestureClick()
{
HandManger[] handMangers = GameObject.FindObjectsOfType<HandManger>(); //無論手上握住任何東西都卸載
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); //廣播使用手勢的事件碼 可以使用手勢 點(diǎn)擊圓盤其他按鈕的時(shí)候廣播 不可用手勢識別 false
}
}
Gesture:
BaseGestureRecognition
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Edwon.VR;
using Edwon.VR.Gesture;
/// <summary>
/// 手勢識別基類 抽象類
/// </summary>
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; //監(jiān)聽事件 自動(dòng)補(bǔ)全方法
}
public virtual void OnDestroy() //虛方法
{
GestureRecognizer.GestureDetectedEvent -= GestureRecognizer_GestureDetectedEvent;//移除監(jiān)聽
}
/// <summary>
/// 當(dāng)手勢被檢測到
/// </summary>
/// <param name="gestureName"></param>
/// <param name="confidence"></param>
/// <param name="hand"></param>
/// <param name="isDouble"></param>
private void GestureRecognizer_GestureDetectedEvent(string gestureName, double confidence, Handedness hand, bool isDouble = false) //手勢名稱 識別精度 左右手 是否雙手
{
OnGestureDetectedEvent(gestureName, confidence);
}
/// <summary>
/// 開始手勢識別 受保護(hù)
/// </summary>
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<Button>();
btn_Back.onClick.AddListener(() =>
{
EventCenter.Broadcast(EventDefine.ShowGestureMainPanel);
gameObject.SetActive(false);
});
txt_GestureName = transform.Find("txt_GestureName").GetComponent<Text>();
txt_GestureConfidence = transform.Find("txt_GestureConfidence").GetComponent<Text>();
EventCenter.AddListener(EventDefine.ShowGextureDetectedPanel, Show);
gameObject.SetActive(false);
}
IEnumerator Dealy(string gestureName, double confidence)
{
txt_GestureName.text = gestureName;
txt_GestureConfidence.text = confidence.ToString("F3"); //小數(shù)點(diǎn)后面三位
yield return new WaitForSeconds(0.5f);
txt_GestureName.text = "";
txt_GestureConfidence.text = "";
}
public override void OnDestroy()
{
base.OnDestroy();
EventCenter.RemoveListener(EventDefine.ShowGextureDetectedPanel, Show);
}
private void Show()
{
gameObject.SetActive(true);
BeginRecognition();
}
public override void OnGestureDetectedEvent(string gestureName, double confidence)
{
StartCoroutine(Dealy(gestureName, confidence));
}
}
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;
/// <summary>
/// 手勢所對應(yīng)的所有的手勢記錄list
/// </summary>
private List<GestureExample> gestureExamples = new List<GestureExample>();
private List<GameObject> exampleObjList = new List<GameObject>();
/// <summary>
/// 手勢名字
/// </summary>
private string m_GestureName;
/// <summary>
/// 判斷是否開始錄制
/// </summary>
private bool m_IsStartRecord = false;
private void Awake()
{
gestureSettings = Utils.GetGestureSettings();
gestureRig = VRGestureRig.GetPlayerRig(gestureSettings.playerID);
EventCenter.AddListener<string>(EventDefine.ShowGestureEditPanel, Show);
EventCenter.AddListener(EventDefine.FinishedOnceRecord, FinishedOnceRecord);
EventCenter.AddListener<bool>(EventDefine.UIPointHovering, UIPointHovering);
Init();
}
private void Init()
{
txt_GestureName = transform.Find("txt_GestureName").GetComponent<Text>();
btn_Back = transform.Find("btn_Back").GetComponent<Button>();
btn_Back.onClick.AddListener(() =>
{
BeginTraining();
m_IsStartRecord = false;
EventCenter.Broadcast(EventDefine.ShowGestureInfoPanel);
gameObject.SetActive(false);
});
btn_Record = transform.Find("btn_Record").GetComponent<Button>();
btn_Record.onClick.AddListener(BeginRecord);
gameObject.SetActive(false);
}
private void OnDestroy()
{
EventCenter.RemoveListener<string>(EventDefine.ShowGestureEditPanel, Show);
EventCenter.RemoveListener(EventDefine.FinishedOnceRecord, FinishedOnceRecord);
EventCenter.RemoveListener<bool>(EventDefine.UIPointHovering, UIPointHovering);
}
private void Show(string gestureName)
{
m_GestureName = gestureName;
gameObject.SetActive(true);
txt_GestureName.text = gestureName;
BeginEditGesture(gestureName);
}
/// <summary>
/// 開始訓(xùn)練 重新學(xué)習(xí)一次
/// </summary>
private void BeginTraining()
{
gestureSettings.BeginTraining(FinishTraining);
}
private void FinishTraining(string netName)
{
}
/// <summary>
/// 獲取射線是否檢測到UI
/// </summary>
/// <param name="value"></param>
private void UIPointHovering(bool value)
{
if (m_IsStartRecord)
{
if (value)
{
gestureRig.uiState = VRGestureUIState.Gestures;
}
else
{
BeginRecord();
}
}
}
/// <summary>
/// 完成一次手勢記錄得錄制會(huì)調(diào)用到這個(gè)方法
/// </summary>
private void FinishedOnceRecord()
{
GetGestureAllExample(m_GestureName);
GenerateExamplesGrid();
}
/// <summary>
/// 開始錄制手勢
/// </summary>
private void BeginRecord()
{
m_IsStartRecord = true;
gestureRig.BeginReadyToRecord(m_GestureName);//錄制手勢
}
/// <summary>
/// 開始編輯手勢
/// </summary>
/// <param name="gestureName"></param>
private void BeginEditGesture(string gestureName)
{
gestureRig.uiState = VRGestureUIState.Editing;
gestureRig.BeginEditing(gestureName);
GetGestureAllExample(gestureName);
GenerateExamplesGrid();
}
/// <summary>
/// 獲取手勢的所有記錄
/// </summary>
/// <param name="gestureName"></param>
public void GetGestureAllExample(string gestureName)
{
gestureExamples = Utils.GetGestureExamples(gestureName, gestureSettings.currentNeuralNet);
foreach (var item in gestureExamples)
{
if (item.raw) //規(guī)整大小
{
item.data = Utils.SubDivideLine(item.data);
item.data = Utils.DownScaleLine(item.data);
}
}
}
/// <summary>
/// 生成所有得記錄
/// </summary>
public void GenerateExamplesGrid()
{
foreach (var obj in exampleObjList)
{
Destroy(obj);
}
exampleObjList.Clear();
for (int i = 0; i < gestureExamples.Count; i++)
{
GameObject go = Instantiate(go_GestureExampleItem, transform.Find("Parent"));
go.GetComponent<GestureExampleItem>().Init(gestureExamples[i].name, i);
LineRenderer line = go.GetComponentInChildren<LineRenderer>();
line.useWorldSpace = false;
line.material = m_Mat;
line.startColor = Color.blue;
line.endColor = Color.green;
float lineWidth = 0.01f;
line.startWidth = lineWidth - (lineWidth * 0.5f);
line.endWidth = lineWidth + (lineWidth * 0.5f);
line.positionCount = gestureExamples[i].data.Count;
for (int j = 0; j < gestureExamples[i].data.Count; j++)
{
gestureExamples[i].data[j] = gestureExamples[i].data[j] * 40;
}
line.SetPositions(gestureExamples[i].data.ToArray());
exampleObjList.Add(go);
}
}
}
GestureMainPanel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Edwon.VR;
using Edwon.VR.Gesture;
/// <summary>
/// 手勢識別
/// </summary>
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<Button>();
btn_GestureInfo.onClick.AddListener(() => //手勢按鈕點(diǎn)擊事件設(shè)置
{
//進(jìn)入手勢信息頁面
EventCenter.Broadcast(EventDefine.ShowGestureInfoPanel);
gameObject.SetActive(false);
});
btn_GestureDetect = transform.Find("btn_GestureDetect").GetComponent<Button>();
btn_GestureDetect.onClick.AddListener(() =>
{
//進(jìn)入手勢測試界面
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<string>(EventDefine.ShowSkillChoosePanel, Show);
Init();
}
private void Init()
{
transform.Find("btn_Back").GetComponent<Button>().onClick.AddListener(() =>
{
//更換技能
for (int i = 0; i < transform.Find("Parent").childCount; i++)
{
if (transform.Find("Parent").GetChild(i).GetComponent<Toggle>().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<string>(EventDefine.ShowSkillChoosePanel, Show);
EventCenter.RemoveListener<string>(EventDefine.ShowSkillChoosePanel, Show);
}
private void Update()
{
for (int i = 0; i < transform.Find("Parent").childCount; i++)
{
if (transform.Find("Parent").GetChild(i).GetComponent<Toggle>().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<Toggle>().isOn = true;
transform.Find("Parent").GetChild(i).GetChild(0).gameObject.SetActive(true);
}
else
{
transform.Find("Parent").GetChild(i).GetComponent<Toggle>().isOn = false;
transform.Find("Parent").GetChild(i).GetChild(0).gameObject.SetActive(false);
}
}
}
}