VR hand tracker game on Steam Vive
Role: Programmer and designer
Platform: C# + Unity + Steam Vive + VR
Demo
Collaborated with programmer and designer Huijie Bao, artist Sandra Liu, artist Wenbo Guo, sound designer Yu’an Tan.
Made a Monster Manager for designer to add custom monsters.
· Used custom struct. So that designer can configure custom monster easily.
 screenshot of Inspector
Quick Time Event system.
· An easily used QTE system. Other programer can add a new QTE event by on interface. This system contains trigger event, condition, success event, fail event, qte time, etc.
namespace QuickTimeEventNamespace {
    public enum QuickTimeEventState { run, success, fail, start }
    public class QuickTimeEvent
    {
        public QuickTimeEvent(float timeInterval_, Action OnTriggerEvent_, Action SucceedEvent_, Action FailureEvent_, Func PassCondition_, bool bContinuous_, Action OnUpdateEvent_)
        {
            timeInterval = timeInterval_;
            OnTriggerEvent = OnTriggerEvent_;
            SucceedEvent = SucceedEvent_;
            FailureEvent = FailureEvent_;
            PassCondition = PassCondition_;
            bContinuous = bContinuous_;
            OnUpdateEvent = OnUpdateEvent_;
        }
        public float timeInterval { get; set; }
        public Action OnTriggerEvent { get; set; }
        public Action SucceedEvent { get; set; }
        public Action FailureEvent { get; set; }
        public Func PassCondition { get; set; }
        public bool bContinuous { get; set; }
        public Action OnUpdateEvent { get; set; }
        public QuickTimeEventState state = QuickTimeEventState.start;
        public void Update()
        {
            if (state != QuickTimeEventState.run)
            {
                return;
            }
            bool result = PassCondition();
            if (OnUpdateEvent != null)
            {
                OnUpdateEvent();
            }            
            if (result)
            {
                Debug.Log("qte success! play success event!");
                SucceedEvent();
                state = QuickTimeEventState.success;
                QTEMgr.Instance.ContinueQTE();
            }
        }
        public void StartQTE()
        {
            //Debug.Log("Start QTE!!!");
            OnTriggerEvent();
            state = QuickTimeEventState.run;
            TimeMgr.Instance.AddDelayEvent(timeInterval, QTEFail);
        }
        public void QTEFail()
        {
            Debug.Log("state: " + state);
            if (state != QuickTimeEventState.run)
            {
                return;
            }
            FailureEvent();
            state = QuickTimeEventState.fail;
            QTEMgr.Instance.ContinueQTE();
        }
    }
    public class QTEMgr : MonoBehaviour
    {
        public static QTEMgr Instance = null;
        public float QTEInterval;
        private int currentQTEIndex = 0;
        private List QTEQueue = new List();
        private QuickTimeEvent currentQTE;
        // --------------------------example-------------------------------
        private int currentNum;
        public TMP_Text baseValueText;
        public GameObject successText;
        public GameObject failureText;
        private int userInput = -99;
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(this.gameObject);
            }
            else
            {
                Instance = this;
            }
        }
        // Start is called before the first frame update
        void Start()
        {
        }
        // Update is called once per frame
        void Update()
        {
            if (currentQTE == null)
            {
                return;
            }
            currentQTE.Update();
        }
        public void AddNewQTE(float timeInterval_, Action OnTriggerEvent_, Action SucceedEvent_, Action FailureEvent_, Func PassCondition_, bool bContinuous_, Action OnUpdateEvent_)
        {
            QTEQueue.Add(new QuickTimeEvent(timeInterval_, OnTriggerEvent_, SucceedEvent_, FailureEvent_, PassCondition_, bContinuous_, OnUpdateEvent_));
        }
        public void StartNewQTE()
        {
            currentQTE = QTEQueue[currentQTEIndex];
            currentQTE.StartQTE();
        }
        public void ContinueQTE()
        {
            currentQTE = null;
            currentQTEIndex++;
            if (currentQTEIndex >= QTEQueue.Count)
            {
                return;
            }
            QuickTimeEvent nextQTE = QTEQueue[currentQTEIndex];
            if (!nextQTE.bContinuous)
            {
                return;
            }
            TimeMgr.Instance.AddDelayEvent(QTEInterval, StartNewQTE);
        }
</code>
</pre>
## Main Gameplay