2015年8月26日 星期三

UNITY3D - 用程式更改animation關鍵影格 change animation clip property value by script

有時候我們會需要物件的移動數值是可調整的,但可能因為架構上大量使用mecanim(animator)導致難以改用程式去控制物件移動。
這時候我們可以用程式更改animator所讀取的animation clip,將裡面的關鍵影格資訊改成所需要的數值。
善加利用state machine加上可變動的animation,mecanim的使用彈性就更高了。

所用到的function : AnimatorOverrideControllerAnimationClip.SetCurveAnimationClip.AddEvent

AnimationClip.SetCurve只會新增或蓋掉原本clip中有設定的property,要刪除某個property則在第四個參數(AnimationCurve)傳入null即可。

※注意,AnimationClip.SetCurve只在Editor上有效!

Runtime會更改專案中animation clip的寫法
//Change transform.localPosition.x move 0~100
//Change sprite.color.a 1~0
//Add event call Ready and pass parameter on 1sec
//gameObject structure:  gameObject:transform
//                           |
//                           --- child:SpriteRenderer
void ChangeAnimCurve () {
    Animator _animator = GetComponent();
    AnimatorOverrideController myOverrideController = new AnimatorOverrideController();
    myOverrideController.runtimeAnimatorController = _animator.runtimeAnimatorController;
    AnimationClip clip = myOverrideController["clipname"];
    clip.SetCurve("", typeof(Transform), "localPosition.x", new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 100f)));
    clip.SetCurve("child", typeof(SpriteRenderer), "m_Color.a", new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f)));
    AnimationEvent evt = new AnimationEvent ();
    evt.functionName = "Ready";
    evt.intParameter = 1;
    evt.time = 1f; //make sure there got a keyframe
    clip.AddEvent (evt); //events added with AddEvent will only persist until play mode is exited of player is quit.
    _animator.runtimeAnimatorController = myOverrideController;
}




不更改專案中animation clip的寫法
//Change transform.localPosition.x move 0~100
//Change sprite.color.a 1~0
//Add event call Ready and pass parameter on 1sec
//gameObject structure:  gameObject:transform
//                           |
//                           --- child:SpriteRenderer
void ChangeAnimCurve () {
    Animator _animator = GetComponent();
    AnimatorOverrideController myOverrideController = new AnimatorOverrideController();
    myOverrideController.runtimeAnimatorController = _animator.runtimeAnimatorController;
    AnimationClip clip = new AnimationClip();
    clip.SetCurve("", typeof(Transform), "localPosition.x", new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 100f)));
    clip.SetCurve("child", typeof(SpriteRenderer), "m_Color.a", new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f)));
    AnimationEvent evt = new AnimationEvent ();
    evt.functionName = "Ready";
    evt.intParameter = 1;
    evt.time = 1f; //make sure there got a keyframe
    clip.AddEvent (evt); //events added with AddEvent will only persist until play mode is exited of player is quit.
    myOverrideController["clipname"] = clip;
    _animator.runtimeAnimatorController = myOverrideController;
}

2015年6月9日 星期二

遊戲探討 — FPS/TPS射擊遊戲準心設計

因為眼力不好所以很少玩射擊遊戲,但最近有在進行射擊相關的遊戲開發,就來研究一下射擊遊戲的"眉角"。

射擊遊戲一般都有準心輔助玩家瞄準目標物;跟現實射擊類似,由視角槍口目標物三點成三角形,子彈在一定距離下才會準確命中目標物。


而遊戲為了體貼玩家,避免摸索這個有效距離,會設計成以準心對到的物體為有效距離再以槍口倒推這個三角形(實做上是以準心射出射線,再以射線終點當目標點,子彈從槍口朝目標點移動)
目標點近時
(這畫面視角不好畫出準心、目標物、槍口的三角形,直角只是槍口跟目標物的交叉,與下圖做比較可發現三角形的不同)

目標點遠時


但這有個問題是連射並且目標點改變(物體移動或消失)狀況下,會發現子彈軌跡改變,下兩張圖準心接近但可以很明顯看到軌跡不同。

為了放大這問題把準心移到角落,方塊為子彈圓球為槍口(起始點),
假設目標物較近時子彈軌跡

目標物消失或目標改為較後方的另一目標物時子彈軌跡


改善這問題的方法就是盡量拉近準心跟槍口的距離(縮小三角形面積,讓軌跡變化變小),連射時加上隨機偏差值(讓玩家忽略軌跡改變)。

也可能有別的改善方法,希望有人能提出來讓大家參考看看。