Chat Room

บทที่ 2 Gameinfo & Pawn & Controller


เรามาเริ่ม บทที่สองกันดีกว่า
จะขึ้นอีกวันนึงละ

ผมจะมาเริ่มจาก class เดิมที่ผมเคยสร้างไว้นะครับ
นั่นคือ TestGame

เรามาทวนความจำ โดย บทที่ 1.2 กันก่อนดีกว่า
บทที่ 1.2

หลังจากคุณไปทวนความจำเสร็จเรียบร้อย
มาเรามาเริ่มกัน

ก่อนอื่น ผมจะลบ auto state ออกไป เหลือแค่ class กับ Default แบบนี้


Class TestGame Extends Gameinfo;
DefaultProperties{
}

ผมก็จะสร้างอีก สอง class ไว้เผื่อก่อน
สร้างไฟล์ใน folder เดียวกับ TestGame นะจะได้ไม่เกิดปัญหา

ผมจะสร้าง file ที่ชื่อว่า MyController และ MyPawn
สร้าง Class ตามชื่อไฟล์

Class MyPawn Extends GamePawn;

DefaultProperties{
}
//--------------------------------------------------
Class MyController Extends PlayerController;

DefaultProperties{
}

เรามาเริ่มที่ Class TestGame ก่อน
ผมจะเพิ่มตรง DefaultProperties ข้างในผมจะใส่ว่า

PlayerControllerClass=class' MyController'



**************** เจอกับตัวเลย UDK รุ่นใหม่ๆเดี๋ยวนี้ พางง ฮ่าๆๆ ปีกกาเปิด ผิดบรรทัด ทำเอา Default ไม่ทำงานเลยทีเดียว


DefaultProperties{
}

ให้เปลี่ยนเป็นแบบนี้

DefaultProperties
{
}


************************************************************************


ต่อ
หลังจากนั้นก็จะได้


DefaultProperties
{
PlayerControllerClass=class'MyController'
}

ตอนนี้ ได้ทำการเชื่อมกับ class MyController แล้วเรียบร้อย
ให้ใส่เพิ่มต่อไปว่า
ก็จะกลายเป็น

DefaultProperties
{

bRestartLevel = false;
bDelayedStart=false;

PlayerControllerClass=class'MyController'
}

ทำไมถึงต้อง สองตัวนี้

bRestartLevel << เริ่มด่านใหม่หรือไม่ ตอบ false ไม่ต้องอ่ะ จะอยู่ใน map นี้ เพราะถ้าไม่ใส่ยังไงมันก็ฟ้องว่า ด่านใหม่ตูอยู่ไหน!!
bDelayedStart << สั่งให้มี Delay ภายหลังหรือไม่ false ไม่เกิดเลย


หลังจากนั้น ให้เติมอีกตัวนึง


DefaultPawnClass=class'MyPawn'


แล้วทีนี้ Unit ก็จะวิ่งได้ แต่ยังไม่ได้มี Model แต่ Controller รู้แล้วว่า เรามีการ Pawn เกิดขึ้นแล้วฉะนั้นพรุ้งนี้
เช้าผมจะมาต่อการใส่ Model ของ Pawn แล้วก็ตามด้วย Camera หลายๆรูปแบบ ครับ
สำหรับวันนี้ นอนก่อน เดี๋ยว พรุ้งนี้มาแก้ บทความแต่เช้าเลย

มาเรามาต่อกัน

เราจะมาเข้า MyPawn กัน ซึ่ง พิมพ์จะพิมพ์ใน  Default ว่า
Begin Object Class=SkeletalMeshComponent Name=Robot

Begin Object Class คือการเริ่มเรียก Class ที่สำเร็จรูปอยู่แล้วมาใช้งาน โดยในนี้จะเป็น
SkeletalMeshComponant ซึ่งเป็น Class ในการดึง Mesh มาใช้งาน แล้วหลังจากนั้นผมตั้งชื่อว่า Robot
เพื่อจะเอาไป add ครับ
SkeletalMesh=SkeletalMesh'หาไฟล์มาใส่'
หลังจากนั้นผมจะทำการ กำหนด SkeletalMesh ให้มันโดย เข้าไปเลือกใน Editor
// เลือก File ใน Editor มาใช้งาน

SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
หลังจากนั้นให้
End object
แล้วก็
Mesh = Robot
Componant.add(Robot)

Begin Object Class=SkeletalMeshComponent Name=Robot
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
End Object
Mesh=Robot ;
Components.Add(Robot);



ก็จะได้ Model ดังภาพ ดังนั้นเวลาวิ่งจะทื่อครับ ฉะนั้นผมยังไม่ได้ใส่ AnimTree หรือ Animset ครับ
เอาละ เราจะรู้ได้ไงว่าเราเอา Model มาจากไหน ก่อนอื่นเข้า Editor ครับ


Begin Object Class=DynamicLightEnvironmentComponent Name=env
bIsCharacterLightEnvironment=TRUE
End Object

ซึ่ง bIsCharacterLightEnvironment ก็คือทำให้ Character ได้รับแสงจากสภาพแวดล้อม



แล้วก็ทำการ add
Components.Add(env)
กับ
LightEnvironment=env
เข้าไป
หลังจากนั้น เพิ่ม LightEnvironment=env ใน object name robot ที่เราสร้างขึ้นไว้แล้ว

===================================================================

Class MyPawn Extends Pawn;

DefaultProperties
{
Begin Object Class=DynamicLightEnvironmentComponent Name=env
bIsCharacterLightEnvironment=TRUE
End Object
Components.Add(env)
LightEnvironment=env

Begin Object Class=SkeletalMeshComponent Name=Robot
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
LightEnvironment=env
End Object
Mesh=Robot;
Components.Add(Robot);
}

====================================================================

ก็จะได้ออกมา ดังรูป



ต่อไปผมจะมา add
การเคลื่อนไหวของ Model ก่อนละกันนะครับ

เรามาหา animSet กันก่อน
ไปที่ Editor อีกครั้ง ของผมจะเลือก ติ๊ก animSet แล้วกด all assets ครับ



หลังจากนั้น ผมจะเลือก K_AnimHuman_BaseMale นะครับ เราสามารถ เข้าไปตรวจดูว่า มี skeletal Mesh
ตัวไหน ใช้งานร่วมกันได้



ถ้ามันขยับเหมือนตัวต้นฉบับได้ก็แสดงว่า ตัวนั้นถูก กระทำโดย ActorX แล้วเรียบร้อยแล้วซึ่งก็หมายความ
ว่า Model นั้นถูกตั้งค่าการเคลื่อนไหวมาแล้วเรียบร้อย แล้วถูกจัดสันส่วนประกอบนั่นเอง

ผมจะเลือกตัวนี้นะครับวิธีก็ใส่ animeset นะครับก็จะเหมือนกับการ ใส่ Mesh แต่ AnimSet จะเป็น array
ให้ใส่แบบนี้

// เลือก File ใน Editor มาใช้งาน
AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'

หลังจากนั้นผมจะมาทำการใส่
Physicsasset
เรามาเข้าใจกันก่อนว่า Physicsasset นั่นคือการทำให้ Model มีค่าเป็น physics ที่ทาง UDK จัดสรรนั่นเอง
โดย ในที่นี้ Physics ตัวนี้จะทำงานคู่กับ Ragdoll เมื่อการเกิดทำให้เกิด Ragdoll จะทำให้ Physicsasset ก็จะเริ่มทำงาน

ตัวอย่าง  Ragdoll


Ragdoll คือ Physics อย่างหนึ่งทาง Computer ซึ่งจะเป็น physics ที่เคลื่อนไหวไปในทิศทาง การ falling หรือทางแรงโน้นถ่วงโลก

ตัวอย่าง


// เลือก File ใน Editor มาใช้งาน
PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'


วิธีการหาก็เหมือนกับข้างบนเปะ เลยครับ แต่ติ๊กจาก animation sets ให้ติ๊กเป็น All นะครับ
หลังจากได้แล้ว ที่ขาดไม่ได้เลยคือ

AnimTree ซึ่งตัวนี้ ช่วยให้เราไม่ต้องสร้าง script การเคลื่อนไหวในรูปแบบต่างๆ ของ Unit ได้
เช่น การ moveing falling swimming jumping อื่นๆอีก move แกนไหน หันหน้า หันตัว ได้อีกตัว แหงนหน้า
ไปทางไหนได้อีกตัว ตัวนี้ ใน Editor สดวกมากๆ

ฉะนั้นวิธีหาก็เหมือนเดิมครับ แต่ใน Object Type มันไม่มีให้ติ๊ก ให้เราพิมพ์ช่องค้นหา ก็คือ AnimTree
ในที่นี้ผมจะเลือก AT_CH_Human เนื่องจาก เรามาดูกันต้องดูภาพตาม



นั่นก็คือ ใน AT_CH_Human ของ AnimTree เขา set ไว้ให้หมดแล้วผมจึงใช้ตัวนี้แทนครับ
หลังจากนั้น ก็ใส่ AT_CH_Human เหมือนเดิม

ตัวอย่าง

// เลือก File ใน Editor มาใช้งาน
AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'


มาเรามาลองดู code ทั้งหมดกัน


Class MyPawn Extends Pawn;

DefaultProperties
{
Begin Object Class=DynamicLightEnvironmentComponent Name=env
bIsCharacterLightEnvironment=TRUE
End Object
Components.Add(env)
LightEnvironment=env

Begin Object Class=SkeletalMeshComponent Name=Robot
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
LightEnvironment=env
AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
End Object
Mesh=Robot;
Components.Add(Robot);
}

อั่นแน่ะ เคลื่อนไหวได้แล้ว

เดี๋ยวเรามาเล่น เสียงกันเพิ่มเติมและการปรับกล้องใน Class Pawn




มาต่อโดยกล้อง จาก Pawn ครับ

เราจะใช้ function ที่ชื่อว่า Calc Camera

โดยการเขียน simulated function เพื่อแทรกการทำงาน ก่อนหน้านี้
โดย วิธีการเขียน ก็คือ

Class MyPawn Extends GamePawn;
<< แทรกตรงนี้
DefaultProperties
{

Begin Object Class=DynamicLightEnvironmentComponent Name=env
bIsCharacterLightEnvironment=TRUE
End Object
Components.Add(env)
LightEnvironment=env

Begin Object Class=SkeletalMeshComponent Name=Robot
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
LightEnvironment=env
AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
End Object
Mesh=Robot;
Components.Add(Robot);

}

ผม ก็สร้าง function ขึ้นมาชื่อว่า

simulated function bool CalcCamera(float Time,out vector loc,out rotator rot,out float fov){

}

function นี้จะเป็นการ ตั้งค่ากล้องเริ่มต้นนะครับ ส่วนใหญ่จะใช้เป็นตัวการที่ใช้ตั้งค่ากล้องเริ่ม
การ Pawn นั่นเองLocation คือพื้นที่นั่นเอง
ส่วนถ้าเราใช้ใน Class Pawn นั้นไม่ต้องประกาศ this หรือ Pawn อีกรอบเลยครับ หรือไม่ต้องประกาศ MyPawn แต่อย่างใด
ให้เราใช้ Location ไปเลยโดด เรามาดูด้าน Parameter กันดีกว่า loc นั้น ผมได้สร้าง เอาไว้เพื่อ
ส่ง ค่า location ของกล้องออกไปทำงานใน class camera นั่นเอง และ rotator ด้วยเช่นกัน
เพราะฉะนั้น เรามาดูตัวอย่างเลยดีกว่า


simulated function bool CalcCamera(float Time,out vector loc,out rotator rot,out float fov){
                  loc = vect(0,0,200);
                  return bool;
}

ท่านจะได้เห็นแต่ภาพมืดๆ นั่นก็เพราะว่า loc ผม fix ไว้ตายตัว คือ พื้นที่ แกน X = 0 Y = 0 Z = 200
vect นั่นจะเป็นตัวจะเป็นตัวจำกัดข้างใน vect จะ return ค่าเป็น vector
vector คือ ตำแหน่งของ 3D นั่นเอง โดย vector จะมีแกน XYZ

แล้ว Rotator จะมี 3 ตัวจะคล้ายๆกับ XYZ โดย ดูได้จากรูป จะมี Roll Pitch Yawข



ครับ ดังนั้น ถ้าใครเรียน sin cos จะรู้ดี ส่วนถ้าใครไม่ได้เรียน จะมี ค่า สูงสุด คือ 16000 ต่ำสุดคือ
0 และ ค่ากลับ คือ -16000 ครับ

สามารถ เช็คได้


simulated function bool CalcCamera(float Time,out vector loc,out rotator rot,out float fov){
                  loc = location;
                  rot = rotation
                 `log(rot.pitch);
                  return true;
}

แล้วลองหมุนหน้าจอดู แล้วไปดูที่ Log ใน command ดูมาอธิบายขยายความนิดนึง

Controll.rotation ก็คือส่วนที่เราบังคับนั้นเอง ส่วนประกอบของ Controll ก็คือ Input เดี๋ยวเรามาเจาะ
ลึกกันอีกทีครับ

วิธี fix ทำให้กล้องเป็น camera แบบ ในเกม Warcraft3



simulated function bool CalcCamera(float Time,out vector loc,out rotator rot,out float fov){
                  loc = location;
                  rot = rotation;         // Line 5
                  rot.pitch = -12050;
                  loc.Z = 500;
                  return true;
}















ก็จะได้มุมมองแบบ ในรูปออกมา สูงขึ้น ใช้เม้าส์หมุน ซ้ายขวาได้แต่หมุนขึ้นหมุนลงไม่ได้ครับ
เพราะผม fix pitch ไว้แล้วครับ แล้วมุมสูงขึ้นก็มาจาก แกน Z ผม ตั้งค่าไว้ที่ 500 ครับ
ลองเล่นดูละกันครับ


สรุป

CalcCamera : เป็น function ที่กำหนดการเริ่มต้นค่าของ กล้อง player ที่ติดต่อ กับการ pawn ครับ

SkeletalMeshComponent  : เป็น class ที่กำหนด SkeletalMesh ครับส่วนใหญ่จะใช้ในการแสดงรูปร่างของ object

DynamicLightEnvironmentComponent  : เป็นการกำหนดด้านแสงครับ โดย SkeletalMeshComponent  มักจะดึงไปใช้ครับเพื่อให้ shadow อะไรพวกนี้ทั้งหลายแหล่ ที่เรา Render ออกมาได้แสดงผลจริงๆครับ


bRestartLevel : เป็นการกำหนดว่าเราต้องการเริ่มต้นหรือไม่ โดย ถ้า เป็น false คือยังไม่ได้เริ่มต้น ให้เลือก false นะครับ
bDelayedStart : เป็นการกำหนดว่าเราต้องการเกิดเลยหรือไม่ True เกิดเลย false ยังจนกว่าจะคลิก
PlayerControllerClass : เป็นการกำหนด class Controller การเชื่อมต่อ Class PlayerController นั่นเองครับ

3 ความคิดเห็น:

Start กล่าวว่า...

โหดมาก

แหล่งเรียนรู้โปรแกรมกราฟฟิคต่างๆ กล่าวว่า...

รบกวนดูโค๊ดให้หน่อยครับว่าผิดตรงใหนครับ
Class MyPawn Extends Pawn;
defaultproperties
simulated function bool CalcCamera(float Time,out vector loc,out rotator rot,out float fov){
loc = vect(0,0,200);
return bool;
}
Begin Object Class=DynamicLightEnvironmentComponent Name=env
bIsCharacterLightEnvironment=TRUE
End Object
Components.Add(env)
LightEnvironment=env
Begin Object Class=SkeletalMeshComponent Name=Robot
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
LightEnvironment=env
AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
End Object
Mesh=Robot;
Components.Add(Robot);

ขอบคุณน่ะครับ บทความดีๆ

Unknown กล่าวว่า...

ให้แก้เป็นแบบนี้ครับ


Class MyPawn Extends Pawn;

simulated function bool CalcCamera(float Time,out vector loc,out rotator rot,out float fov){
loc = vect(0,0,200);
return bool;
}
defaultproperties
{
Begin Object Class=DynamicLightEnvironmentComponent Name=env
bIsCharacterLightEnvironment=TRUE
End Object
Components.Add(env)
LightEnvironment=env
Begin Object Class=SkeletalMeshComponent Name=Robot
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
LightEnvironment=env
AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'
SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
End Object
Mesh=Robot;
Components.Add(Robot);
}