การแก้ไขจะทำงานอย่างไรเพื่อทำให้การเคลื่อนที่ของวัตถุราบรื่นขึ้น?


10

ฉันถามคำถามที่คล้ายกันสองสามครั้งในช่วง 8 เดือนที่ผ่านมาโดยไม่มีความสุขจริง ๆ ดังนั้นฉันจะทำให้คำถามทั่วไปยิ่งขึ้น

ฉันมีเกม Android ซึ่งเป็น OpenGL ES 2.0 ภายในนั้นฉันมี Game Loop ดังต่อไปนี้:

ลูปของฉันทำงานบนหลักการขั้นตอนเวลาที่แน่นอน (dt = 1 / ticksPerSecond )

loops=0;

    while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){

        updateLogic(dt);
        nextGameTick+=skipTicks;
        timeCorrection += (1000d/ticksPerSecond) % 1;
        nextGameTick+=timeCorrection;
        timeCorrection %=1;
        loops++;

    }

    render();   

การรวมของฉันทำงานเช่นนี้:

sprite.posX+=sprite.xVel*dt;
sprite.posXDrawAt=sprite.posX*width;

ตอนนี้ทุกอย่างทำงานได้สวยตามที่ฉันต้องการ ฉันสามารถระบุได้ว่าฉันต้องการให้วัตถุเคลื่อนที่ในระยะหนึ่ง (ความกว้างของหน้าจอพูด) ภายใน 2.5 วินาทีและจะทำเช่นนั้น นอกจากนี้เนื่องจากการข้ามเฟรมที่ฉันอนุญาตในลูปเกมของฉันฉันสามารถทำได้บนอุปกรณ์ใด ๆ และมันจะใช้เวลา 2.5 วินาที

ปัญหา

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

ฉันยังไม่แน่ใจว่าทำไมกรอบข้ามไป แต่ฉันอยากจะชี้ให้เห็นว่านี่คือสิ่งที่จะทำอย่างไรกับประสิทธิภาพที่ไม่ดีฉันได้นำรหัสกลับไปที่ 1 สไปรต์เล็ก ๆ และไม่มีตรรกะ (นอกเหนือจากตรรกะที่ต้อง ย้ายเทพดา) และฉันยังได้ข้ามเฟรม และนี่คือแท็บเล็ต Google Nexus 10 (และตามที่กล่าวไว้ข้างต้นฉันต้องข้ามเฟรมเพื่อให้ความเร็วคงที่ในทุกอุปกรณ์)

ดังนั้นตัวเลือกเดียวที่ฉันมีคือการใช้การแก้ไข (หรือการคาดการณ์) ฉันอ่านบทความทุกฉบับที่นั่น แต่ก็ไม่มีใครช่วยฉันให้เข้าใจว่ามันทำงานได้อย่างไรและการนำไปใช้ที่พยายามทั้งหมดของฉันล้มเหลว

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

ดังนั้นฉันสับสนจริงๆ ผู้คนบอกว่าคุณไม่ควรเปลี่ยนตำแหน่งของวัตถุจากภายในวิธีการแสดงผล แต่ตัวอย่างทั้งหมดออนไลน์แสดงสิ่งนี้

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

แก้ไข

ข้อมูลเพิ่มเติม - ตัวแปรที่ใช้ในการวนรอบเกม

private long nextGameTick = System.currentTimeMillis();
//loop counter
private int loops;
//Amount of frames that we will allow app to skip before logic is affected
private final int maxFrameskip = 5;                         
//Game updates per second
final int ticksPerSecond = 60;
//Amount of time each update should take        
private final int skipTicks = (1000 / ticksPerSecond);
float dt = 1f/ticksPerSecond;
private double timeCorrection;

และเหตุผลของการโหวตคือ ................... ?
BungleBonce

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

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

ขอบคุณ Noctrine มันทำให้ฉันรำคาญจริงๆเมื่อผู้คน downvote โดยไม่ต้องอธิบาย @SethBattin ขอโทษใช่แน่นอนคุณพูดถูกการกระโดดข้ามเฟรมนั้นทำให้เกิดอาการกระตุกได้อย่างไรก็ตามการแก้ไขบางอย่างควรแก้ไขสิ่งนี้เหมือนกับที่ฉันพูดไปแล้วว่าฉันประสบความสำเร็จ (แต่ จำกัด ) หากฉันผิดฉันก็เดาว่าจะเป็นเช่นไรฉันจะทำให้มันทำงานได้อย่างราบรื่นด้วยความเร็วเดียวกันกับอุปกรณ์ต่าง ๆ ?
BungleBonce

4
อ่านเอกสารเหล่านั้นซ้ำ ๆ พวกเขาไม่ได้แก้ไขตำแหน่งของวัตถุในวิธีการแสดงผล พวกเขาเพียงแก้ไขตำแหน่งที่ชัดเจนของวิธีการตามตำแหน่งสุดท้ายและตำแหน่งปัจจุบันตามจำนวนเวลาที่ผ่านไป
AttackingHobo

คำตอบ:


5

มีสองสิ่งสำคัญที่จะทำให้การเคลื่อนไหวราบรื่นขึ้นอย่างแรกคือสิ่งที่คุณต้องการเพื่อให้ตรงกับสถานะที่คาดไว้ ณ เวลาที่เฟรมถูกนำเสนอให้กับผู้ใช้ข้อที่สองคือคุณต้องนำเสนอเฟรมให้กับผู้ใช้ ในช่วงเวลาที่ค่อนข้างคงที่ การนำเสนอเฟรมที่ T + 10ms จากนั้นอีกเฟรมที่ T + 30ms และอีกเฟรมที่ T + 40ms จะปรากฏต่อผู้ใช้ในการตัดสินแม้ว่าสิ่งที่แสดงจริงสำหรับช่วงเวลาเหล่านั้นจะถูกต้องตามการจำลอง

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

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

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

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

ดังนั้นเมื่อต้องการใส่ลงในลูป pseudocode ฉันคิดว่าคุณต้องการอะไรมากกว่านี้

InitialiseWorldState();

previousTime = currentTime = 0.0;
renderInterval = 1.0 / 60.0; //A nice high starting interval

subFrameProportion = 1.0; //100% currentFrame, 0% previousFrame

while (true)
{
    frameStart = ActualTime();

    //Render the world state as if it was some proportion 
    // between previousTime and currentTime
    // E.g. if subFrameProportion is 0.5, previousTime is 0.1 and 
    // currentTime is 0.2, then we actually want to render the state
    // as it would be at time 0.15. We'd do that by interpolating 
    // between movingObject.previousPosition and movingObject.currentPosition
    // with a lerp parameter of 0.5
    Render(subFrameProportion); 

    //Check we've not taken too long and missed our render interval
    frameTime = ActualTime() - frameStart;
    if (frameTime > renderInterval)
    {
        renderInterval = frameTime * 1.2f; //Give us a more reasonable render interval that we actually have a chance of hitting
    }

    expectedFrameEnd = frameStart + renderInterval;

    //Loop until it's time to render the next frame
    while (ActualTime() < expectedFrameEnd)
    {
        //step the simulation forward until it has moved just beyond the frame end
        if (previousTime < expectedFrameEnd) &&
            currentTime >= expectedFrameEnd)
        {
            previousTime = currentTime;

            Update();
            currentTime += fixedTimeStep;

            //After the update, all objects will be in the position they should be for
            // currentTime, **but** they also need to remember where they were before,
            // so that the rendering can draw them somewhere between previousTime and
            //  currentTime

            //Check again we've not taken too long and missed our render interval
            frameTime = ActualTime() - frameStart;
            if (frameTime > renderInterval)
            {
                renderInterval = frameTime * 1.2f; //Give us a more reasonable render interval that we actually have a chance of hitting
                expectedFrameEnd = frameStart + renderInterval
            }
        }
        else
        {
            //We've brought the simulation to just after the next time
            // we expect to render, so we just want to wait.
            // Ideally sleep or spin in a tight loop while waiting.
            timeTillFrameEnd = expectedFrameEnd - ActualTime();
            sleep(timeTillFrameEnd);
        }
    }

    //How far between update timesteps (i.e. previousTime and currentTime)
    // will we be at the end of the frame when we start the next render?
    subFrameProportion = (expectedFrameEnd - previousTime) / (currentTime - previousTime);
}

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

class MovingObject
{
    Vector velocity;
    Vector previousPosition;
    Vector currentPosition;

    Initialise(startPosition, startVelocity)
    {
        currentPosition = startPosition; // position at time 0
        velocity = startVelocity;
        //ignore previousPosition because we should never render before time 0
    }

    Update()
    {
        previousPosition = currentPosition;
        currentPosition += velocity * fixedTimeStep;
    }

    Render(subFrameProportion)
    {
        Vector actualPosition = 
            Lerp(previousPosition, currentPosition, subFrameProportion);
        RenderAt(actualPosition);
    }
}

และวางโครงร่างไทม์ไลน์เป็นมิลลิวินาทีโดยบอกว่าการเรนเดอร์ใช้เวลา 3 มิลลิวินาทีในการดำเนินการอัปเดตใช้เวลา 1 มิลลิวินาทีขั้นตอนการอัปเดตของคุณจะถูกกำหนดไว้ที่ 5 มิลลิวินาทีและเรนเดอร์

0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33
R0          U5  U10 U15 U20 W16                                 R16         U25 U30 U35 W32                                 R32
  1. ครั้งแรกที่เราเริ่มต้นที่เวลา 0 (ดังนั้น currentTime = 0)
  2. เราแสดงสัดส่วน 1.0 (เวลาปัจจุบัน 100%) ซึ่งจะดึงดูดโลกในเวลา 0
  3. เมื่อเสร็จสิ้นแล้วเวลาจริงคือ 3 และเราไม่คาดหวังว่าเฟรมจะสิ้นสุดจนถึง 16 ดังนั้นเราจึงจำเป็นต้องเรียกใช้การอัปเดตบางอย่าง
  4. T + 3: เราอัปเดตตั้งแต่ 0 ถึง 5 (ดังนั้นหลังจากนั้น currentTime = 5, previousTime = 0)
  5. T + 4: ยังก่อนเฟรมจะสิ้นสุดดังนั้นเราอัปเดตจาก 5 เป็น 10
  6. T + 5: ยังก่อนเฟรมจะสิ้นสุดดังนั้นเราอัปเดตตั้งแต่ 10 ถึง 15
  7. T + 6: ยังก่อนเฟรมจะสิ้นสุดดังนั้นเราอัปเดตจาก 15 เป็น 20
  8. T + 7: ยังอยู่ก่อนเฟรมสิ้นสุด แต่ปัจจุบันเวลาอยู่เหนือเฟรมสิ้นสุด เราไม่ต้องการจำลองอีกต่อไปเพราะการทำเช่นนั้นจะผลักดันเราเกินกว่าเวลาที่เราต้องการแสดงผลต่อไป เรารออย่างเงียบ ๆ แทนช่วงเวลาเรนเดอร์ถัดไป (16)
  9. T + 16: ถึงเวลาที่จะเรนเดอร์อีกครั้ง ก่อนหน้านี้เวลา 15, เวลาปัจจุบันคือ 20 ดังนั้นหากเราต้องการเรนเดอร์ที่ T + 16 เราจะผ่าน 1 มิลลิวินาทีผ่านการประทับเวลานาน 5ms ดังนั้นเราจึง 20% ของทางผ่านเฟรม (สัดส่วน = 0.2) เมื่อเราเรนเดอร์เราวาดวัตถุ 20% ของวิธีระหว่างตำแหน่งก่อนหน้าและตำแหน่งปัจจุบัน
  10. วนกลับไปที่ 3 และทำต่อไปเรื่อย ๆ

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


NB: pseudocode อ่อนแอในสองวิธี ประการแรกมันไม่จับตัวมรณะ (ใช้เวลานานกว่า fixedTimeStep to Update, หมายถึงการจำลองที่ตกไปไกลกว่าเดิม, วนรอบไม่สิ้นสุด), renderInterval ไม่เคยถูกทำให้สั้นลงอีก ในทางปฏิบัติคุณต้องการเพิ่มโหมดเรนเดอร์ทันที แต่เมื่อเวลาผ่านไปมันจะค่อย ๆ ย่อให้สั้นที่สุดเท่าที่จะทำได้เพื่อให้ได้กรอบเวลาจริง ไม่เช่นนั้นการอัปเดตที่ไม่ดี / ยาวจะทำให้คุณมีอัตราเฟรมต่ำตลอดไป
MrCranky

ขอบคุณสำหรับ @MrCranky นี้แน่นอนว่าฉันต้องดิ้นรนหาวิธี จำกัด การเรนเดอร์ในวงของฉัน! แค่คิดออกไม่ได้ว่าจะทำอย่างไรและสงสัยว่านั่นอาจเป็นปัญหาหรือไม่ ฉันจะอ่านให้ถูกต้องและลองทำตามคำแนะนำของคุณจะรายงานกลับ! ขอขอบคุณอีกครั้ง :-)
BungleBonce

ขอบคุณ @MrCranky ตกลงฉันอ่านแล้วอ่านคำตอบของคุณอีกครั้ง แต่ฉันไม่เข้าใจ :-( ฉันพยายามที่จะใช้มัน แต่มันให้หน้าจอที่ว่างเปล่าฉันดิ้นรนกับเรื่องนี้จริง ๆ ก่อนหน้านี้และเฟรมปัจจุบันฉันคิดว่า เกี่ยวข้องกับตำแหน่งก่อนหน้าและตำแหน่งปัจจุบันของวัตถุที่กำลังเคลื่อนที่ของฉันนอกจากนี้สิ่งที่เกี่ยวกับบรรทัด "currentFrame = Update ();" - ฉันไม่ได้รับสายนี้หมายความว่า call update () นี้เพราะฉันไม่เห็นว่า อื่นฉันกำลังเรียก update หรือมันหมายถึงการตั้งค่าปัจจุบัน frame (ตำแหน่ง) เป็นค่าใหม่หรือไม่ขอบคุณอีกครั้งสำหรับความช่วยเหลือของคุณ !!
BungleBonce

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

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

3

สิ่งที่ทุกคนบอกคุณนั้นถูกต้อง อย่าอัปเดตตำแหน่งการจำลองของเทพดาในตรรกะการเรนเดอร์ของคุณ

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

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

นอกจากนั้นดูเหมือนว่าคุณจะมีความเข้าใจที่ดี หวังว่านี่จะช่วยได้


ยอดเยี่ยม @MilliamMorrison - ขอบคุณสำหรับการยืนยันนี้ฉันไม่เคยแน่ใจจริง ๆ 100% ว่านี่เป็นกรณีนี้ฉันคิดว่าฉันกำลังจะได้งานนี้ในระดับหนึ่ง - ไชโย!
BungleBonce

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

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

ใช่มันเป็นปัญหาที่ยุ่งยากในการแก้ไข ฉันได้ถามคำถามแยกต่างหากเกี่ยวกับเรื่องนี้ที่นี่gamedev.stackexchange.com/questions/83230/ถ้าคุณต้องการจับตามองหรือมีส่วนร่วม ตอนนี้สิ่งที่คุณแนะนำในความคิดเห็นของคุณฉันไม่ได้ทำแล้ว? (Interpolating ระหว่างเฟรมก่อนหน้าและเฟรมปัจจุบัน)?
BungleBonce

ไม่มาก ตอนนี้คุณกำลังคาดการณ์จริง ๆ คุณใช้ข้อมูลล่าสุดจากการจำลองและคาดการณ์ว่าข้อมูลนั้นเป็นอย่างไรหลังจากการประทับเวลาแบบเศษส่วน ฉันขอแนะนำให้คุณแก้ไขระหว่างตำแหน่งการจำลองล่าสุดและตำแหน่งการจำลองปัจจุบันด้วยการจับเวลาเศษส่วนสำหรับการแสดงผลแทน การแสดงผลจะอยู่เบื้องหลังการจำลองโดย 1 การประทับเวลา สิ่งนี้ทำให้แน่ใจได้ว่าคุณจะไม่ทำให้วัตถุในสถานะที่การจำลองไม่ได้ตรวจสอบ (เช่นกระสุนปืนจะไม่ปรากฏในกำแพงเว้นแต่การจำลองล้มเหลว)
William Morrison
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.