ฉันควรใช้ความเร็วกับ addForce เมื่อจัดการกับวัตถุผู้เล่นเมื่อใด


18

ฉันสับสนเกี่ยวกับสองวิธีนี้ใน Unity framework ทั้งทำให้ผู้เล่นย้ายวัตถุหยุดเปลี่ยนทิศทางและอื่น ๆ เมื่อใดควรใช้อีกอันหนึ่งและอีกอันหนึ่งเหมาะสมหรือไม่



@ Byte56 ทั้งสองคำถามกำลังถามเกี่ยวกับสิ่งต่าง ๆ
Robert

1
แตกต่างกัน แต่เกี่ยวข้องกัน นั่นเป็นสาเหตุที่พวกเขาเชื่อมโยงและไม่ซ้ำกัน แสดงมันปรากฏขึ้นในคอลัมน์ที่เชื่อมโยงทางด้านขวา
MichaelHouse

คำตอบ:


13

คุณจะใช้velocityเพื่อย้ายวัตถุในอัตราคงที่ (เช่นสัญลักษณ์แสดงหัวข้อย่อย) และAddForce()เพื่อเพิ่มการเคลื่อนไหว (ตัวอย่างเช่น thruster ยานอวกาศ) โปรดทราบว่ามี "การเคลื่อนไหว" สองประเภท แรงและแรงกระตุ้น สำหรับยานอวกาศทรัสเตอร์คุณต้องใช้แรงกระตุ้น


4
คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงชอบแรงกระตุ้นสำหรับยานอวกาศ นี่อาจเป็นสิ่งที่ไม่เหมาะถ้าคุณใช้การเร่งความเร็วแบบค่อยเป็นค่อยไปเมื่อเวลาผ่านไปแทนที่จะเปลี่ยนโมเมนตัมทันทีเนื่องจากสิ่งต่าง ๆ เช่นผลกระทบของอาวุธ นำไปใช้ในช่วงเวลาหนึ่งโดยทั่วไปคุณจะต้องการแรง (หรือความเร่งถ้าคุณไม่ต้องการให้มวลเป็นปัจจัย) ในขณะที่คุณใช้แรงกระตุ้นทันที (หรือตามลำดับ velocityChange)
DMGregory

@DMGregory ใช่มันขึ้นอยู่กับชนิดของแรงที่คุณต้องการเพิ่ม ในตัวอย่างของยานอวกาศทรัสเตอร์ซึ่งเป็นการระเบิดพลังงานชั่วขณะจากนั้นแรงกระตุ้นเป็นตัวเลือกที่ถูกต้อง
trojanfoe

2
ไม่ชัดเจนในทันทีว่าคุณหมายถึงการยิงระยะสั้นของเจ็ททัศนคติหรือการเผาไหม้อย่างต่อเนื่องของเครื่องยนต์หลัก ("thruster" ใช้บิตทั่วไปใน sci-fi ในบางครั้ง) ดังนั้นฉันคิดว่าฉันควรชี้แจงให้คนอื่นลอง ใช้แรงกระตุ้นสำหรับผู้สนับสนุนจรวด ;)
DMGregory

@DMGregory แน่นอน; คำศัพท์เฉพาะทางเทคโนโลยีอวกาศของฉันส่วนใหญ่อิงจากภาพยนตร์ :)
trojanfoe

@trojanfoe Go play KSP เหมือนตอนนี้
user253751

21

แม้ว่าจะมีคำตอบที่ยอมรับแล้ว แต่ฉันคิดว่ามีรายละเอียดเพิ่มเติมที่คุ้มค่า

ใช้ Velocity

เมื่อคุณตั้งค่าความเร็วคุณจะเอาชนะทุกสิ่งที่อาจส่งผลต่อการเคลื่อนไหวของวัตถุนั้นอย่างแน่นอน ในบางสถานการณ์สิ่งนี้เป็นที่น่าพอใจเช่นการตั้งค่าความเร็วเริ่มต้นของกระสุนหนึ่งครั้งในขณะที่มันถูกไล่ออกเช่นเดียวกับในตัวอย่างของโทรจัน เพียงระวังเพราะเมื่อใช้ในสถานการณ์ที่ไม่ถูกต้องอาจทำให้เกิดปัญหา:

  • หากหลายแหล่ง / สคริปต์พยายามที่จะปรับเปลี่ยนความเร็วของ Rigidbody เดียวกันโดยการตั้งค่าโดยตรง (เช่น. body.velocity = foo) ดังนั้นสิ่งใดก็ตามที่ชนะครั้งสุดท้ายและอีกอันหนึ่งไม่มีผลกระทบใด ๆ สิ่งนี้สามารถนำไปสู่ลำดับของการอัพเดทบั๊กโดยเฉพาะอย่างยิ่งทำให้เอนทิตี้ของเลื่อนหรือตกลงช้า (เนื่องจากการเร่งลงเนื่องจากแรงโน้มถ่วงถูกแทนที่ก่อนที่มันจะสะสม)

  • หากคุณตั้งค่าความเร็วทุกเฟรมการชนกับวัตถุอื่นอาจแปลกไปบ้าง ราวกับว่าวัตถุของคุณถูกขับเคลื่อนด้วยเครื่องยนต์ที่มีแรงบิดไม่ จำกัด ไม่ว่าความเร็วจะลดลงแค่ไหนมันก็กลับไปที่ความเร็วสูงสุดในขั้นตอนฟิสิกส์ถัดไปและความเร็วจะไม่เบี่ยงเบนไปจากแรงกระแทก . สิ่งนี้สามารถนำไปสู่การเปิดตัววัตถุที่คุณชนหรือวัตถุขนาดเล็กที่สามารถผลักวัตถุขนาดใหญ่ได้ง่ายกว่าที่ควรจะเป็นหรือวัตถุที่เลื่อนอย่างช้าๆไปตามสิ่งกีดขวางแบบคงที่แทนที่จะเบี่ยงเบนออกไป

บางครั้งอาจต้องการเอฟเฟกต์เหล่านี้ ตัวอย่างเช่นเมื่อฉันสร้างเกม Kinect และฉันต้องการแขนขาเสมือนจริงของผู้เล่นเพื่อให้สามารถโต้ตอบกับฉากฟิสิกส์ฉันมักจะย้ายร่างกายเหล่านั้นโดยใช้การตั้งค่าความเร็วโดยตรง เนื่องจากมือที่แท้จริงของผู้เล่นอยู่ในสถานที่ที่รู้จักและไม่ได้ช้าลงจากการชนกับวัตถุเสมือนนั้นมือเสมือนจริงของพวกเขาต้องทำแบบเดียวกันเพื่อให้อยู่ในแนวเดียวกันดังนั้นในกรณีนี้เราต้องการแทนที่ลักษณะพิเศษทางฟิสิกส์อื่น ๆ ทั้งหมด ไปถึงที่นั่น

เพิ่มและบังคับเพื่อน

AddForceและฟังก์ชั่นผู้ช่วยที่คล้ายกันได้ถูกสร้างขึ้นเพื่อให้ความร่วมมือกับทุกสิ่งที่เกิดขึ้นในโลกฟิสิกส์ หากมีหลายแหล่งที่มา / สคริปต์ AddForce ไปยัง Rigidbody เอฟเฟกต์ทั้งหมดเหล่านี้จะถูกรวมเข้าด้วยกันเพื่อสร้างการเปลี่ยนแปลงสุทธิในการเคลื่อนไหวของวัตถุ (ซึ่งขึ้นอยู่กับวิธีการคำนวณ สิ่งนี้จะช่วยหลีกเลี่ยงสคริปต์ตัวเดียวที่ทำให้เกิดเอฟเฟกต์ฟิสิกส์อื่น ๆ

AddForce มาในสี่รสชาติโดยการระบุพารามิเตอร์ ForceModeซึ่งเป็นประโยชน์สำหรับสิ่งต่าง ๆ :

ForceMode       |   Use
-----------------------------------------------------------------------
Force (default) |   Accelerate an object over 1 time step, based on its mass.
                |   Units: Newtons = kg * m/s^2
                |
Acceleration    |   Accelerate an object over 1 time step, ignoring its mass. (like gravity)
                |   Units: m/s^2
                |
Impulse         |   Instantaneously propel an object, based on its mass
                |   Units: N * s = kg * m/s
                |
VelocityChange  |   Instantaneously propel an object, ignoring its mass
                |   (like body.velocity = foo, except multiple scripts can stack)
                |   Units:  m/s

หากคุณกำลังพยายามที่จะสร้างแบบจำลองการผลักดันอย่างต่อเนื่องในช่วงเวลา (เช่นสิ่งที่คุณใช้ทุกคงที่ UpdateUpdate) เช่นการขับรถหรือการเผาไหม้จรวดหรือแรงโน้มถ่วงดึงดีคุณต้องการแรงหรือการเร่งความเร็ว (ขึ้นอยู่กับว่าคุณต้องการให้วัตถุหนักเร่งความเร็วช้าลงหรือไม่)

หากคุณกำลังสร้างแบบจำลองการเคลื่อนไหวที่ฉับพลันและเฉียบแหลมอย่างเช่นการยิงกระสุนปืนถอยกลับจากการระเบิดหรือกระเด้งออกมาจากสิ่งกีดขวางคุณก็จะต้องการ Impulse หรือ VelocityChange มากขึ้น

การใช้ AddForce ช่วยให้คุณได้รับความสมจริงทางกายภาพมากขึ้น แต่ก็อาจต้องการให้คุณใช้เวลาในการคิดผ่านฟิสิกส์ของพฤติกรรมของคุณมากขึ้น ตัวอย่างเช่นหากคุณต้องการให้ร่างกายของคุณมีการเร่งความเร็วสูงสุดถึงความเร็วเป้าหมายเพื่อให้ตอบสนองต่อการชนได้สมจริงกว่าการตั้งค่าความเร็วทุกเฟรมคุณอาจต้องการการคำนวณที่คล้ายกับฟังก์ชันตัวช่วยนี้:

public static void AccelerateTo(this Rigidbody body, Vector3 targetVelocity, float maxAccel)
{
    Vector3 deltaV = targetVelocity - body.velocity;
    Vector3 accel = deltaV/Time.deltaTime;

    if(accel.sqrMagnitude > maxAccel * maxAccel)
        accel = accel.normalized * maxAccel;

    body.AddForce(accel, ForceMode.Acceleration);
}

เหตุผลที่ฉันเรียกสิ่งเหล่านี้ว่า "ฟังก์ชั่นผู้ช่วย" คือในทางเทคนิคคุณสามารถบรรลุจุดสิ้นสุดเดียวกันทั้งหมดด้วย:

 body.velocity += suitablyCalculatedDeltaV;

( ฉันคิดว่ามันเป็นไปได้ที่นักฟิสิกส์ฟิสิกส์ที่ใช้ PhysX / Box2D จะเปลี่ยนบัฟเฟอร์ผ่าน AddForce แยกจากกัน แต่ฉันไม่เห็นผลที่ชัดเจนจากสิ่งนี้)

ดังนั้นในตอนท้ายของวันที่สิ่งที่ฟังก์ชั่นเหล่านี้จะได้รับจริงๆเราก็คือความชัดเจนของความตั้งใจ เมื่อฉันต้องการใช้แรงแบบค่อยเป็นค่อยไปฉันไม่จำเป็นต้องจำเพิ่ม deltaV ของฉันด้วย Time.deltaTime และหารด้วยมวลฉันแค่บอกว่าฉันต้องการ ForceMode.Force และจัดการอย่างถูกต้องและสอดคล้องกัน และเมื่อฉันหรือคนอื่นมาทำซ้ำในรหัสของฉันในภายหลังมันชัดเจนในสิ่งที่ฉันหมายถึงโดยไม่จำเป็นต้องถอดรหัสเวลาและการคำนวณจำนวนมากเพื่อคิดออก


6

นอกจากคำตอบของ trojanfoeแล้ว Angry Birds vs Car Racing ตัวอย่างที่สำคัญและแตกต่างกันสองวิธี ( AddForceและvelocityตามลำดับ) ตัวอย่างเช่นใน Angry Birds การใช้ความเร็วนั้นยากขึ้นอีกเล็กน้อยเนื่องจากคุณต้องตั้งวิถีกระสุนด้วยตนเองเช่น

เมื่อฉันใช้ AddForce ใน Angry Birds ฉันจะใช้

_birdRigidbody.AddForce(new Vector2(5,5));

ในขณะที่เมื่อฉันใช้ความเร็วฉันจะจัดการวิถีการใช้

x = v*t*Cos(theta) y = v*t*Sin(theta) - 0.5 * g * t *t

หรืออะไรทำนองนี้

ในขณะที่อยู่ในเกม Car Racing คุณจะต้องควบคุมความเร็วตลอดเวลาไม่เหมือน Angry Birds เช่น Shoot และ all ดังนั้นในที่จับสถานการณ์จะเป็นประโยชน์มากกว่าvelocityAddForce

หวังว่าคุณจะเข้าใจ. อย่างน้อยก็น้อย


1
ตัวอย่าง AngryBirds ของคุณน่าจะใช้โมเมนตัมการเปลี่ยนแปลงทันที (เช่น Impulse หรือ VelocityChange) เมื่อ slingshot ถูกปล่อยออกมาแทนที่จะเป็น ForceMode.Force เริ่มต้นซึ่งจำลองผลกระทบของมันในช่วงเวลาหนึ่ง คุณสามารถปรับตัวเลขเพื่อให้ได้พฤติกรรมที่เท่าเทียมกันจากทั้งสองวิธี แต่ถ้าคุณเปลี่ยนขั้นตอนเวลาที่แน่นอนของคุณวิธีการแก้ปัญหาแรงจะมีเอาท์พุทที่แตกต่างกัน (เพราะมันรวมพลังในช่วงเวลานานหรือสั้นกว่า) ในขณะที่แรงกระตุ้น ที่ต้องการเพราะมันเป็นเพียงช่วงเวลาของการเปิดตัว
DMGregory

0

Rigidbody Velocity และ Rigidbody Addforce เป็นฟังก์ชั่นสองอย่างที่สับสนใน Unity 3D และผู้เริ่มต้นมักจะไม่เข้าใจถึงความแตกต่าง ในบทความนี้เราจะพูดถึงความแตกต่างระหว่าง RigidBody.velocity และ RigidBody.addforce

ในทั้งสองกรณีไม่ว่าจะเป็นฟังก์ชันเสริมหรือความเร็วเราจะใช้คำว่าแรงเพื่ออธิบาย

เมื่อเราใช้ Rigidbody.velocity ดังนั้นในกรณีนี้เรากำลังเพิ่มแรงให้กับวัตถุของเรา แต่แรงนี้จะเคลื่อนย้ายวัตถุเท่านั้นเว้นแต่และจนกว่าเราจะใช้กำลังต่อไป

ตัวอย่างเช่น

body.velocity = Vector3 ใหม่ (0,0,5);

สมมติว่าคุณเพิ่มตำแหน่ง 5f ในตำแหน่ง z และแรงนั้นจะถูกเพิ่มเมื่อคุณกดปุ่ม W ดังนั้นเมื่อคุณจะกดปุ่ม W วัตถุจะเริ่มต้นด้วยความเร็ว 5 ทันทีมันก็เหมือนกันถ้าคุณเพิ่มแรงโดยใช้ฟังก์ชั่นนี้กับรถยนต์รถคันนั้นจะเริ่มที่ความเร็ว 5

body.velocity = Vector3 ใหม่ (0,0,200);

และถ้าคุณบอกว่าเปลี่ยนค่าเป็น 200 แล้วหลังจากบันทึกกด W. Car จะเริ่มทำงานด้วยความเร็ว 200 จากการเริ่มต้นซึ่งเป็นไปไม่ได้ในโลกแห่งความจริง

ตอนนี้ถ้าคุณพูดถึง Rigidbody.addforce

โดยดำเนินการต่อตัวอย่างรถยนต์ของเรา ถ้าคุณเพิ่มแรง 200 ลงในรถ

body.addforce (0,0,200);

รถจะไม่เริ่มเคลื่อนที่ด้วยความเร็ว 200 ถ้าเรากด W แต่เริ่มจากช้าแล้วเพิ่มความเร็วและหยุดตามค่าของ Drag

Rigidbody.addforce เริ่มช้าแล้วเร่งความเร็วเหมือนกับที่คุณลากโต๊ะหนักก่อนอื่นคุณจะเริ่มดันโต๊ะนั้นโต๊ะจะขยับจากตำแหน่งเดิมเล็กน้อย แต่ถ้าคุณดันโต๊ะนั้นมันจะเริ่มเคลื่อนที่ & ถ้าคุณออกจากตารางนั้นมันจะครอบคลุมระยะทางบางอย่างขึ้นอยู่กับพื้นผิวและนั่นก็เป็นสิ่งเดียวกัน

คุณสามารถใช้ Rigidbody.velocity ที่คุณต้องการย้ายวัตถุของคุณเพื่อตอบสนองทันทีเช่นผู้เล่นกระโดดและผลของแรงนั้นจะหายไปหลังจากการกระโดดและคุณสามารถใช้ Rigidbody.addforce ที่คุณต้องการเริ่มต้นช้าและจากนั้นการเคลื่อนไหวอย่างต่อเนื่องเช่น จรวด หากคุณใช้ Rigidbody.addforce ในการกระโดด Player / Object จะยังคงอยู่ในอวกาศสักครู่แล้วจะกลับมาสู่พื้นดิน

(ที่มา)


อย่างน้อยคุณควรลองปรับโพสต์ของคุณเป็นรูปแบบของคำตอบ Stack Exchange :)
Vaillancourt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.