วิธีที่มีประสิทธิภาพที่สุดในการแปลง Vector3 เป็น Vector2


11

วิธีที่มีประสิทธิภาพและรวดเร็วที่สุดในการแปลง Vector3 เป็น Vector2 คืออะไร

การคัดเลือกนักแสดง:

Vector2 vector2 = (Vector2)vector3;

การเริ่มต้น Vector2 ใหม่:

Vector2 vector2 = new Vector2(vector3.x, vector3.y);

หรือมีวิธีอื่นที่ฉันไม่รู้


11
การดำเนินการของโครงสร้างเหล่านี้จะไม่เป็นปัญหาคอขวดในการกำหนดประสิทธิภาพของคุณดังนั้นแทนที่จะปล่อยให้จมอยู่ในการเพิ่มประสิทธิภาพแบบไมโครเช่นนี้ฉันขอแนะนำให้ใช้สิ่งใดก็ตามที่ชัดเจนกว่าเพื่อทำความเข้าใจในบริบทที่คุณใช้ มัน. ;)
DMGregory

3
@DMGregory: ยกเว้นว่าแน่นอนว่า OP ได้ทำการวิเคราะห์ประสิทธิภาพแล้วและบางทีอาจเป็นเพราะการชกมวย ตัวอย่างเช่นการวนซ้ำซ้อนกันอาจเป็นการนำ A-star หรือ Dijkstra ไปใช้
Pieter Geerkens

5
@PieterGeerkens Fair แต่ถ้า OP ทำการวิเคราะห์ประสิทธิภาพแล้วพวกเขาจะลองทั้งสองวิธีแล้วและจะมีตัวเลขทั้งคู่ ;) จากการดูเส้นทางการเคลื่อนที่ของจำนวนผู้ใช้ Unity ใหม่ (รวมถึงตัวเอง) ฉันค่อนข้างมั่นใจว่าในกรณีนี้คือการเพิ่มประสิทธิภาพแบบไมโครดังนั้นฉันจึงต้องการเตือนที่แข็งแกร่ง (หากพูดเกินจริง) วิธีนี้คือการปรับแต่งโค้ดเป็นสัปดาห์หรือเป็นเดือนและทำให้เกิดความไม่มั่นใจในแง่ดีในวิธีที่ไม่ทำให้เกมของเราดีขึ้น
DMGregory

คำตอบ:


12
Vector3 v3 = Vector3.one;
Vector2 v2 = v3;

Vector3s สามารถแปลงเป็น Vector2 โดยนัย (z ถูกยกเลิก)

http://docs.unity3d.com/ScriptReference/Vector2-operator_Vector3.html

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

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

TestConvertByOperation 10,000,000 อินสแตนซ์: 0.2714049s

TestConvertByCasting 10,000,000 อินสแตนซ์: 0.286027 วินาที

TestConvertByInitializing 10,000,000 อินสแตนซ์: 0.1458781s

using UnityEngine;

public class TestVector3Conversion : MonoBehaviour
{

    readonly int iterations = 10000000;
    Vector3 testVector = new Vector3(3f, 14f, 42f);

    void Start()
    {
        Debug.Log(string.Format("TestConvertByOperation {0} instances: {1}s", iterations, TestConvertByOperation()));
        Debug.Log(string.Format("TestConvertByCasting {0} instances: {1}s", iterations, TestConvertByCasting()));
        Debug.Log(string.Format("TestConvertByInitializing {0} instances: {1}s", iterations, TestConvertByInitializing()));
    }

    float TestConvertByOperation()
    {
        var timeStart = Time.realtimeSinceStartup;

        for (int i = 0; i < iterations; i++)
        {
            Vector2 v2 = testVector;
        }

        return Time.realtimeSinceStartup - timeStart;
    }

    float TestConvertByCasting()
    {
        var timeStart = Time.realtimeSinceStartup;

        for (int i = 0; i < iterations; i++)
        {
            Vector2 v2 = (Vector2)testVector;
        }

        return Time.realtimeSinceStartup - timeStart;
    }

    float TestConvertByInitializing()
    {
        var timeStart = Time.realtimeSinceStartup;

        for (int i = 0; i < iterations; i++)
        {
            Vector2 v2 = new Vector2(testVector.x, testVector.y);
        }

        return Time.realtimeSinceStartup - timeStart;
    }

}

1
พวกเขาถูกหล่อโดยปริยาย นี้จะกระทำโดยการกำหนดผู้ประกอบการแปลงใหม่ แดกดันความสามัคคีเป็นการละเมิด '... หากการแปลงนั้นรับประกันได้ว่าจะไม่ทำให้ข้อมูลสูญหาย' ส่วนหนึ่ง
Athos vk

1
อัปเดตคำตอบของฉันด้วยตัวอย่างรหัสเพื่อทดสอบวิธีการต่าง ๆ แจ้งให้เราทราบว่ากรณีใดของคุณเร็วกว่า
Mattias

1
ผลลัพธ์จะเปลี่ยนไปเล็กน้อยในบิลด์ / ไม่ใช่ debug หรือเมื่อข้อมูล Vector2 มีอายุการใช้งานนอกวง for (ซึ่งทำให้คอมไพเลอร์ไม่ทำการปรับให้เหมาะสมบางประเภท) ฉันได้รับการแพร่กระจาย 110 ถึง 151 มิลลิวินาทีหรือความแตกต่างสูงสุดประมาณ 4 นาโนวินาทีต่อการมอบหมาย ดังนั้นหากเราไม่ทำหลายร้อยเท่าทุกเฟรมนี่อาจไม่ใช่กรณีที่ต้องกังวลถึงแม้ว่าจะมีความแตกต่างที่วัดได้ในตัวอย่างสังเคราะห์เช่นนี้
DMGregory

1
@DMGregory ตกลง นี่คือเหตุผลที่มันเป็นความคิดที่ดีที่จะทำการทดสอบประสิทธิภาพในบริบทที่ถูกต้องด้วยข้อมูลจริง
Mattias

1
ปัญหาเกี่ยวกับการแปลงโดยนัยคือสิ่งที่yเกิดขึ้น เมื่อแปลงVector3ไปยังVector2คุณมักจะต้องการxและzไม่ได้และx y
Kevin Krumwiede

6

ทั้งสองVector2และVector3เป็นstructในเครื่องยนต์สามัคคีเพื่อสร้างหนึ่งจากที่อื่น ๆ ก็เกี่ยวข้องกับการจัดสรรพื้นที่เก็บข้อมูลในกองที่ (ยกเว้นกรณีที่ปลายทางเป็นคุณลักษณะของ ระดับวัตถุซึ่งจะช่วยให้การกระโดดข้ามขั้นตอนแรกนี้) และการคัดลอกค่าองค์ประกอบทั้งสอง กลไกทั้งสองอย่างที่คุณให้ควรถูกรวบรวมไปยังรหัส IL นี้

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


0

จากการทดสอบของฉันวิธีที่ดีที่สุดคือการกำหนดค่าด้วยตัวเอง

Vector2 vector2;
vector2.x = vector3.x;
vector2.y = vector3.y;

นี่คือผลลัพธ์ของฉันที่ฉันขยายจาก Mattias

TestConvertByOperation 10,000,000 อินสแตนซ์: 0.3220527s

TestConvertByCasting 10,000,000 อินสแตนซ์: 0.3226218s

TestConvertByInitializing 10,000,000 อินสแตนซ์: 0.1916729 วินาที

TestConvertByManualAssign 10,000,000 อินสแตนซ์: 0.09500527s

using UnityEngine;

namespace myTest
{
    public class test: MonoBehaviour 
    {
        readonly int iterations = 10000000;
        Vector3 testVector = new Vector3(3f, 14f, 42f);

        void Start()
        {
            Debug.Log(string.Format("TestConvertByOperation {0} instances: {1}s", iterations, TestConvertByOperation()));
            Debug.Log(string.Format("TestConvertByCasting {0} instances: {1}s", iterations, TestConvertByCasting()));
            Debug.Log(string.Format("TestConvertByInitializing {0} instances: {1}s", iterations, TestConvertByInitializing()));
            Debug.Log(string.Format("TestConvertByManualAssign {0} instances: {1}s", iterations, TestConvertByManualAssign()));
        }

        float TestConvertByOperation()
        {
            var timeStart = Time.realtimeSinceStartup;
            Vector2 v2;
            for (int i = 0; i < iterations; i++)
            {
                v2 = testVector;
            }

            return Time.realtimeSinceStartup - timeStart;
        }

        float TestConvertByCasting()
        {
            var timeStart = Time.realtimeSinceStartup;
            Vector2 v2;
            for (int i = 0; i < iterations; i++)
            {
                v2 = (Vector2)testVector;
            }

            return Time.realtimeSinceStartup - timeStart;
        }

        float TestConvertByInitializing()
        {
            var timeStart = Time.realtimeSinceStartup;
            Vector2 v2;
            for (int i = 0; i < iterations; i++)
            {
                v2 = new Vector2(testVector.x, testVector.y);
            }

            return Time.realtimeSinceStartup - timeStart;
        }
        float TestConvertByManualAssign()
        {
            var timeStart = Time.realtimeSinceStartup;
            Vector2 v2;
            for (int i = 0; i < iterations; i++)
            {
                v2.x = testVector.x;
                v2.y = testVector.y;
            }

            return Time.realtimeSinceStartup - timeStart;
        }
    }
}

โปรดทราบว่าฉันทดสอบด้วยความสามัคคีรุ่น 5.6.5

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