提问人:Andrew Martin 提问时间:9/3/2023 更新时间:9/3/2023 访问量:42
如何在Unity C#中从此游戏对象的克隆中访问变量?
How can I access variables from a clone of this Game Object in Unity C#?
问:
我正在尝试使用 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 游戏对象功能是否是正确的方法,但是我找不到任何将圆圈直接渲染到屏幕上的方法。
答: 暂无答案
评论