如何在Unity C#中从此游戏对象的克隆中访问变量?

How can I access variables from a clone of this Game Object in Unity C#?

提问人:Andrew Martin 提问时间:9/3/2023 更新时间:9/3/2023 访问量:42

问:

我正在尝试使用 Verlet 集成使一堆水粒子在盒子周围反弹并相互反弹。目前,我可以通过使用 Instantiate() 按空格键来生成粒子;方法 另一个脚本。我可以随心所欲地生成任意数量的球,而且效果很好。但是,计算彼此之间的反弹是我遇到问题的地方。Verlet 需要当前位置和最后一个位置来计算速度,我需要计算反弹,目前我无法弄清楚如何从预制件的克隆到另一个克隆获取速度。目前,我能够通过找到这个球与所有其他球之间的距离并查看它是否小于其半径之和来检测碰撞。这对于检测冲突很有效,因为我可以轻松获取每个游戏对象的转换。无所不知的聊天 GPT 告诉我,我可以在脚本中创建一个游戏对象并在检查器中引用它并以这种方式访问它们,但我不确定如何将对象引用到它本身。它还说我可以实例化父对象下的所有游戏对象,并以这种方式访问变量。无论如何,这是我的代码。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaterScript : MonoBehaviour
{


    //Variables for detecting collisions
    public float radius;
    public string cloneTag = "Water";
    private bool collide;
    


    //Variables for Verlet Integration

    public Vector2 pos;
    public Vector2 posLast = new Vector2 (0f, 0f);
    public Vector2 posNext;

    //Particle Properties
    public float mass = 1;
    public float elasticity = 1;


    //Parameters are current position and last position. Outputs next position
    //Calculates the objects next position based on where it is and where it was 
    //Called every frame but posNext can be overriden if it is calculated to be a collision in the next frame
    Vector2 movement(Vector2 pos, Vector2 posLast, float mass)
    {
        //BasicVerletForCalculatingMovement
        posNext[0] = pos[0] + (pos[0] - posLast[0]) + 0f / Time.deltaTime;
        posNext[1] = pos[1] + (pos[1] - posLast[1]) - 0.00000001f / Time.deltaTime;
        return posNext;

    }

    //Vector2 bounce(float x1, float y1, float v1, float x2, float y2, float v2)
    //{
        //v1f = (m1 - m2) * v1i / (m1 + m2) + 2 * m2 * v2i / (m1 + m2)

     //   float velX = (1 - 1) * velX / (2 + 2) + 2 * 1 * 0 / (1 + 1);
    //    float velX = (1 - 1) * velX / (2 + 2) + 2 * 1 * 0 / (1 + 1);
        //v1f = (m1 - m2) * v1i / (m1 + m2) + 2 * m2 * v2i / (m1 + m2)




    //}



    // Start is called before the first frame update
    void Start()
    {
        //movement(new Vector2 (0, 0),new Vector2 (0, 0), 1);
        //Debug.Log(posNext);
    }

    // Update is called once per frame
    void Update()
    {


        //Calls the movement function to calculate the next position
        




   
        //Create a List for all the GameObjects with the "Water" Tag
        GameObject[] waterObjects = GameObject.FindGameObjectsWithTag("Water");
        foreach (GameObject waterObject in waterObjects)
        {

            //Create a Vector for the position of each object
            Vector2 position = waterObject.transform.position;
            Vector2 nextposition = waterObject.transform.position;
            

            //Collision Detection Scripts
            //Pythagorean Theorem to detect if the distance between objects is less than the sum of their radius
            if (((transform.position.x - position[0]) * (transform.position.x - position[0])) 
                + ((transform.position.y - position[1]) * (transform.position.y - position[1])) < radius*radius)
            {
                

                //Detect if the collision is with itself
                if(position[0] == transform.position.x && position[1] == transform.position.y)
                {
                    //Always outputs collision with itself. I was to tired to figure out how to avoid the else statement
                } else
                {

                    //Where I want the bounce code to go


                    Debug.Log("Collide!");
                    

                }

            }

        }
        //defining the respective x and y coordinate constraints and bouncing the ball of the edge in the case of collision
        float wall1 = -15;
        float wall2 = 10;
        float floor1 = -15;
        float floor2 = 10;

        //simply setting the velocity to be opposite depending on which wall it collides with.
        if (transform.position.y < floor1)
        {
            float offset = pos[1] - floor1;
            pos[1] = floor1;
            posLast[1] = floor1 + ((-posLast[1] + floor1) + offset)*elasticity;

        }
        if (transform.position.x < wall1)
        {
            float offset = pos[0] - wall1;
            pos[0] = wall1;
            posLast[0] = wall1 + ((-posLast[0] + wall1) + offset)*elasticity;

        }
        if (transform.position.y > floor2)
        {

            float offset = pos[1] - floor2;
            pos[1] = floor2;
            posLast[1] = floor2 + ((-posLast[1] + floor2) + offset)*elasticity;

        }
        if (transform.position.x > wall2)
        {

            float offset = pos[0] - wall2;
            pos[0] = wall2;
            posLast[0] = wall2 + ((-posLast[0] + wall2) + offset)*elasticity;

        }

        movement(pos, posLast, 1);
        posLast = pos;
        pos = posNext;
        //Debug.Log(pos);
        //float velX = (pos[0] - posLast[0]) + 0f / Time.deltaTime;
        //float velY = (pos[1] - posLast[1]) - 0f / Time.deltaTime;

        transform.position = pos;




        if (transform.position.y < 0.078f)
        {
            //Debug.Log("CollideWithFloor!");
        }




    }


}

我不知道该尝试什么。也许我可以列出上一帧中所有球的位置并从中计算速度?我担心这将是拉姆密集的。此外,任何优化建议将不胜感激。我将制作另一个版本,我只是不确定使用 Unitys 游戏对象功能是否是正确的方法,但是我找不到任何将圆圈直接渲染到屏幕上的方法。

C# unity-game-engine 变量 gameobject

评论

0赞 BugFinder 9/3/2023
好吧,如果你使用物理学,你可以得到碰撞双方的速度(速度和方向)。
0赞 Andrew Martin 9/3/2023
是的,但这会比手动编码更快吗?此外,它不允许我更改一些我想更改的变量。
0赞 BugFinder 9/3/2023
好吧,碰撞可以告诉你什么击中了什么,所以如果你在组件上存储必要的信息,你就可以访问它。一切尽在你的掌控之中。什么更快?谁知道呢,但对我来说,我当然不确定重新发明 phyics 是否是一个计划。但是,我不确定你觉得你不能改变什么。但。。
0赞 Andrew Martin 9/3/2023
我将再次尝试使用 Unity 中内置的碰撞器。我之前尝试过,但遇到了一个问题,即在发生碰撞时它输出了一个事件。此外,物体是否必须具有刚体或仅碰撞体才能检测碰撞?我发现让所有物体都具有刚体是非常缓慢的。在帧开始变得不愉快之前,我可以渲染大约 40 个左右的对象,因此,如果有一种方法可以使用碰撞器返回碰撞数据并编写针对这种情况进行优化的脚本,以便根据返回的数据进行物理计算,那将是首选。
0赞 BugFinder 9/3/2023
40?我预计在你遇到任何真正的问题之前,在几百个左右

答: 暂无答案