Asset Store ของ Unity ถือเป็นแหล่งขุมทรัพย์ของนักพัฒนาอย่างเราเลยก็ว่าได้ เพราะไม่เพียงมีโมเดลให้เราโหลดใช้งานเพียงอย่างเดียว แต่เรายังสามารถหาโปรเจคต่าง ๆ ในนั้น ไว้ดูเป็นตัวอย่างได้อีกด้วย วันนี้ผู้เขียนจึงขอยกโปรเจคโปรเจคหนึ่ง มาให้ดูกัน !!!
ในโปรเจคนี้เราสามารถนำฉากต่าง ๆ มาเช็คและทดลองดูได้ไม่ยาก พร้อมกับมีหลายฉากที่น่าสนใจอีกด้วย ซึ่งในแต่ละฉากเราก็จะได้เห็นการใช้งานของ Reflection Probes, Enlighten, Animation รูปแบบใหม่ และระบบ Audio พร้อมกับอื่น ๆ อีกมากมาย
ENLIGHTEN
- Republique’s Atrium คือฉากแรกที่เราจะนำมาศึกษากันนะครับ โดยส่วนใหญ่แล้วการสร้างฉาก ฉากหนึ่งจะเกิดจากการนำแนวคิดต่าง ๆ ที่มีนำมาทดลองโดยระบบใหม่ ๆ เพื่อจะนำมันมาศึกษาวิธีการใช้งานจริง ๆ ของมัน ซึ่ง The Atrium is Episode 1 จึงถือเป็นผลงานชิ้นดี ที่แสดงให้เห็นคุณภาพสูงสุดของระบบใน Unity 5 ทั้งนี้ในระบบใหม่ที่น่าสนใจคือ Enlighten ที่ถูกปรับปรุงใหม่ โดยเฉพาะ แสงที่ถูกสร้างจากด้านบนของซีน
- Emissive materials ถือเป็นสิ่งใหม่ล่าสุดของ Unity 5 ที่เราจะเห็นได้ว่ามันจะไปเพิ่ม Emission intensity ของ Fluorescent Light material ซึ่งจะทำให้ฉากเราสดใสมากขึ้นจากแสง bounce
- เรายังสามารถเห็นได้จากตัวอย่างของ material ได้ว่า emission value นั้นถือเป็นระบบใหม่ และมันยังง่ายสำหรับการทำอนิเมท โดยการเพิ่ม Animation track เข้าไปควบคุมท่าก็เสร็จเรียบร้อยแล้ว
- ทั้งนี้เราจะเห็นได้ว่า การเพิ่ม Indirect Intensity ใน lighting tab นั้น ฉากที่เป็นแบบไดนามิกจะถูกแก้ไข และกลายเป็น brighter
- Reflection probes สามารถช่วยให้ metals ตอบสนองได้มากขึ้น เช่น real-world counterparts ที่จะเห็นถึงการสะท้อนของสภาพแวดล้อมสิ่งต่าง ๆ หากเราเช็ค Box projections ได้อย่างถูกต้อง เราจะเห็น reflect ของสิ่งแวดล้อมรอบตัวเป็นรูปทรงสี่เหลี่ยม
- ส่วนภาพข้างล่างจะเห็นได้ว่า ถ้าหากเราใช้เสา และเซ็ต surface ของ material เป็น metal จากนั้นเพิ่ม reflectivity เราจะได้การสะท้อนที่ถูกต้อง
- ในกรณีเดียวกัน หากเราลด smoothness จากการสะท้อนจะกลายเป็นขรุขระ หรือพร่ามัว
UNITY 5 AUDIO
- Unity 5 Audio Mixer ช่วยให้เราสามารถจัดหมวดหมู่เสียง และระบุ buses ออกไป ให้มีความยืดหยุ่นมากขึ้น โดยการนำเสียงไป routed และ mixed รวมไปถึงการนำ effects มาใช้งาน ซึ่งใน ‘Ambience’ จะแบ่งออกเป็น 2 แบบ คือ 2D และ 3D โดยปกติแล้ว 3D ambient audio จะถูก routed ไปยังกลุ่ม 3D ย่อย ๆ เพื่อให้เสียงที่เกี่ยวข้องใน 3D bus fire ออกมาเหมาะสม ภายในแต่ละกลุ่ม volume และ pitch สามารถปรับแต่งได้ ซึ่ง audio filters สามารถนำไปใช้ และปรับแต่งได้ โดยเราสามารถ solo individual หรือ mute individual หรือกลุ่มทั้งหมดในตอน Run อยู่ก็ได้ โดยเราแค่กดที่ ‘Edit ใน Play Mode’ ทางด้านขวาบน corner ของ Audio Mixer ในขณะที่โปรเจคกำลังทำงานอยู่ ตัวอย่างเช่นเราเพิ่ม ‘SFX Reverb’ ไปที่กลุ่ม Footsteps เพื่อให้เราสามารถปรับแต่ง และเล่นวนในขณะที่โปรเจคกำลังทำงานอยู่นั่นเอง
- เมื่อเราพอใจกับวิธีการ mix เราสามารถเซฟมันเก็บไว้ได้นะครับ โดยการเซฟ Snapshot ของเราใน Audio Mixer settings ซึ่งนี่จะทำให้เราสร้างเสียงที่มีเอกลักษณ์ และเหมาะสมได้มากที่สุด
MECANIM
- เมื่อเราพร้อมที่จะเล่นเกมแล้ว เราสามารถกดเล่นได้ โดยเราสามารถควบคุมการเคลื่อนที่ต่าง ๆ ของกล้องได้จากปุ่ม WASD หากเรากดคลิกซ้ายยังสามารถคลื่อนที่ Hope ไปยังรอบ ๆ สิ่งแวดล้อมได้ ซึ่งในนี้ได้มีการรวมการอนิเมทต่าง ๆ ไว้แล้ว แต่เนื่องจากมีการเปิดเผย API ของ Mecanim เราจึงสามารถสร้างเครื่องมือในการสร้าง และแก้ไข Mecanim asset ได้
- ในโปรเจคมีปุ่มสร้างใหม่ที่ใช้สำหรับ Animator โดยเราเรียกใช้ได้ผ่านการคลิกที่ Hope ส่วนข้างล่างนี้เป็นสคริปต์ในการสร้าง similar Animator ในโฟลเดอร์โปรเจค
[MenuItem (
"Hope/Create Controller"
)]
static
void
CreateController () {
<i>
var
controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath (
"Assets/HopeScriptCtrl.controller"
);
<i>
controller.AddParameter(
"Walk"
, AnimatorControllerParameterType.Bool);
controller.AddParameter(
"TurnLeft"
, AnimatorControllerParameterType.Bool);
controller.AddParameter(
"TurnRight"
, AnimatorControllerParameterType.Bool);
controller.AddParameter(
"HalfTurn"
, AnimatorControllerParameterType.Bool);
<i>
var
rootStateMachine = controller.layers[0].stateMachine;
var
stateMachineStand = rootStateMachine.AddStateMachine(
"Stand"
);
<i>
var
stateIdle = stateMachineStand.AddState(
"Idle"
);
var
stateTurnLeft = stateMachineStand.AddState(
"TurnLeft"
);
var
stateTurnRight = stateMachineStand.AddState(
"TurnRight"
);
var
stateHalfTurn = stateMachineStand.AddState(
"HalfTurn"
);
var
stateWalk = stateMachineStand.AddState(
"Walk"
);
stateIdle.motion = AssetDatabase.LoadAssetAtPath(
"Assets/Animations/Hope Animations/StandingIdleLooking.fbx"
,
typeof
(AnimationClip))
as
Motion;
stateTurnLeft.motion = AssetDatabase.LoadAssetAtPath(
"Assets/Animations/Hope Animations/MoveStand90_L.fbx"
,
typeof
(AnimationClip))
as
Motion;
stateTurnRight.motion = AssetDatabase.LoadAssetAtPath(
"Assets/Animations/Hope Animations/MoveStand90_R.fbx"
,
typeof
(AnimationClip))
as
Motion;
stateHalfTurn.motion = AssetDatabase.LoadAssetAtPath(
"Assets/Animations/Hope Animations/MoveStand180.fbx"
,
typeof
(AnimationClip))
as
Motion;
stateWalk.motion = AssetDatabase.LoadAssetAtPath(
"Assets/Animations/Hope Animations/MoveWalk_F.fbx"
,
typeof
(AnimationClip))
as
Motion;
<i>
var
idle2TurnLeft = stateIdle.AddTransition (stateTurnLeft);
var
turnLeft2Idle = stateTurnLeft.AddTransition (stateIdle);
idle2TurnLeft.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0,
"TurnLeft"
);
idle2TurnLeft.duration = 0.025f;
turnLeft2Idle.hasExitTime =
true
;
turnLeft2Idle.exitTime = 0.85f;
turnLeft2Idle.duration = 0.15f;
var
idle2TurnRight = stateIdle.AddTransition (stateTurnRight);
var
turnRight2Idle = stateTurnRight.AddTransition (stateIdle);
idle2TurnRight.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0,
"TurnRight"
);
idle2TurnRight.duration = 0.025f;
turnRight2Idle.hasExitTime =
true
;
turnRight2Idle.exitTime = 0.85f;
turnRight2Idle.duration = 0.15f;
var
idle2HalfTurn = stateIdle.AddTransition (stateHalfTurn);
var
halfTurn2Idle = stateHalfTurn.AddTransition (stateIdle);
idle2HalfTurn.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0,
"HalfTurn"
);
idle2HalfTurn.duration = 0.025f;
halfTurn2Idle.hasExitTime =
true
;
halfTurn2Idle.exitTime = 0.85f;
halfTurn2Idle.duration = 0.15f;
var
idle2Walk = stateIdle.AddTransition (stateWalk);
var
walk2Idle = stateWalk.AddTransition (stateIdle);
idle2Walk.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0,
"Walk"
);
idle2Walk.duration = 0.025f;
walk2Idle.AddCondition(UnityEditor.Animations.AnimatorConditionMode.IfNot, 0,
"Walk"
);
walk2Idle.duration = 0.25f;
}
และนี่คือทั้งหมดแล้วสำหรับการนำโปรเจคนี้มาศึกษาดูระบบต่าง ๆ ผู้เขียนคิดว่าเพื่อน ๆ หลายคนคงได้ประโยชน์ แรงบันดาลใจ และความรู้ไปไม่มากก็น้อยนะครับ (^^)
Author Bio
- คมกล้า วันครรชิต เป็นนักตรวจสายตาอายุ 33 ปีที่โรงพยาบาลราชวิถีซึ่งเชี่ยวชาญในการค้นหาโรคตาที่หายากพร้อมกับการรักษาอาการบาดเจ็บที่ตายาก เมื่อเขาไม่ได้ทำงานใช้เวลาส่วนใหญ่กับภรรยา 10 ปี