努力通过 2D 物理模拟在 Unity 中创建轨迹预测
Struggling to create a trajectory prediction in Unity with 2D physics simulation
我在 Unity 中有一个 2D 打砖块风格的游戏,您可以在每次转动前用鼠标选择射击角度。我想展示玩家瞄准时球会做什么的准确轨迹预测,最多可能有 200 帧球运动(目前)。这涉及到可能从顶部、左侧和右侧的墙壁以及任何砖块弹回。
我正在使用物理模拟和线条渲染器来完成此操作,但无法使其正常工作。
它应该将枪支、墙壁和砖块复制到一个虚拟场景中,以玩家瞄准的角度发射一个球,模拟 200 帧的运动,并将它们绘制在线性渲染器中。
这是游戏代码的精简版,简化为只关注第一回合的瞄准和物理模拟。当我 运行 它时,它只是在与枪相同的坐标中绘制线渲染器的 200 个点。
我做错了什么?谢谢!
using UnityEngine;
using UnityEngine.SceneManagement;
public class Aim3 : MonoBehaviour
{
private Vector3 gunPosScreenV3, aimPointScreenV3,
aimPointWorldV3, aimDirectionV3;
private Vector2 ballDirection, ballVelocity;
[SerializeField] private GameObject gun, walls, bricks;
Camera cam;
LineRenderer lr;
// For Physics Scene
private int maxPhysicsFrameIterations = 200;
private Scene simulationScene;
private PhysicsScene2D physicsScene;
[SerializeField] private GameObject ballPrefab;
private GameObject ghostObj;
void Start()
{
lr = GetComponent<LineRenderer>();
lr.enabled = true;
cam = Camera.main;
CreatePhysicsScene();
}
void Update()
{
DrawTrajectory();
}
// This is run once to create a duplicate of the game board for the physics simulation
private void CreatePhysicsScene()
{
simulationScene = SceneManager.CreateScene("Simulation", new CreateSceneParameters(LocalPhysicsMode.Physics2D));
physicsScene = simulationScene.GetPhysicsScene2D();
// Copy the gun to the simulated scene
ghostObj = Instantiate(gun.gameObject, gun.transform.position, gun.transform.rotation);
ghostObj.GetComponent<SpriteRenderer>().enabled = false;
SceneManager.MoveGameObjectToScene(ghostObj, simulationScene);
// Copy all the bricks to the simulated scene. These are stored under a parent Game Object that
// is attached in the editor
foreach (Transform obj in bricks.transform)
{
ghostObj = Instantiate(obj.gameObject, obj.position, obj.rotation);
ghostObj.GetComponent<SpriteRenderer>().enabled = false;
SceneManager.MoveGameObjectToScene(ghostObj, simulationScene);
}
// Copy the top, left, and right walls to the simulated scene. These are invisible and don't have sprites.
// These are stored under a parent Game Object that is attached in the editor
foreach (Transform obj in walls.transform)
{
ghostObj = Instantiate(obj.gameObject, obj.position, obj.rotation);
SceneManager.MoveGameObjectToScene(ghostObj, simulationScene);
}
} // CreatePhysicsScene
private void DrawTrajectory()
{
// Get the starting Screen position of the gun from the World position
gunPosScreenV3 = cam.WorldToScreenPoint(gun.transform.position);
gunPosScreenV3.z = 1;
// Get position of mouse in screen units
aimPointScreenV3 = Input.mousePosition;
// Get the position of the mouse in world units for aiming
aimPointWorldV3 = cam.ScreenToWorldPoint(aimPointScreenV3);
aimPointWorldV3.z = 1;
// Calculate the normalized direction of the aim point compared to the gun
aimDirectionV3 = (aimPointScreenV3 - gunPosScreenV3).normalized;
Physics2D.simulationMode = SimulationMode2D.Script;
// Instantiate the ball prefab for the simulation
ghostObj = Instantiate(ballPrefab, gun.transform.position, Quaternion.identity);
// Assign the ball's velocity
ballDirection = new Vector2(aimDirectionV3.x, aimDirectionV3.y);
ballVelocity = ballDirection * 20f;
ghostObj.GetComponent<Rigidbody2D>().velocity = ballVelocity;
SceneManager.MoveGameObjectToScene(ghostObj.gameObject, simulationScene);
lr.positionCount = maxPhysicsFrameIterations;
for (var i = 0; i < maxPhysicsFrameIterations; i++)
{
physicsScene.Simulate(Time.fixedDeltaTime);
//Physics2D.Simulate(Time.fixedDeltaTime);
lr.SetPosition(i, ghostObj.transform.position);
}
Destroy(ghostObj);
Physics2D.simulationMode = SimulationMode2D.Update;
} // DrawTrajectory
}
您使用了 aimPointScreenV3,但它似乎从来没有 initialized/calculated。
找到答案了。只需要在 将球移动到模拟场景后 添加速度。
SceneManager.MoveGameObjectToScene(ghostObj.gameObject, simulationScene);
ghostObj.GetComponent<Rigidbody2D>().velocity = ballVelocity;
我在 Unity 中有一个 2D 打砖块风格的游戏,您可以在每次转动前用鼠标选择射击角度。我想展示玩家瞄准时球会做什么的准确轨迹预测,最多可能有 200 帧球运动(目前)。这涉及到可能从顶部、左侧和右侧的墙壁以及任何砖块弹回。
我正在使用物理模拟和线条渲染器来完成此操作,但无法使其正常工作。
它应该将枪支、墙壁和砖块复制到一个虚拟场景中,以玩家瞄准的角度发射一个球,模拟 200 帧的运动,并将它们绘制在线性渲染器中。
这是游戏代码的精简版,简化为只关注第一回合的瞄准和物理模拟。当我 运行 它时,它只是在与枪相同的坐标中绘制线渲染器的 200 个点。
我做错了什么?谢谢!
using UnityEngine;
using UnityEngine.SceneManagement;
public class Aim3 : MonoBehaviour
{
private Vector3 gunPosScreenV3, aimPointScreenV3,
aimPointWorldV3, aimDirectionV3;
private Vector2 ballDirection, ballVelocity;
[SerializeField] private GameObject gun, walls, bricks;
Camera cam;
LineRenderer lr;
// For Physics Scene
private int maxPhysicsFrameIterations = 200;
private Scene simulationScene;
private PhysicsScene2D physicsScene;
[SerializeField] private GameObject ballPrefab;
private GameObject ghostObj;
void Start()
{
lr = GetComponent<LineRenderer>();
lr.enabled = true;
cam = Camera.main;
CreatePhysicsScene();
}
void Update()
{
DrawTrajectory();
}
// This is run once to create a duplicate of the game board for the physics simulation
private void CreatePhysicsScene()
{
simulationScene = SceneManager.CreateScene("Simulation", new CreateSceneParameters(LocalPhysicsMode.Physics2D));
physicsScene = simulationScene.GetPhysicsScene2D();
// Copy the gun to the simulated scene
ghostObj = Instantiate(gun.gameObject, gun.transform.position, gun.transform.rotation);
ghostObj.GetComponent<SpriteRenderer>().enabled = false;
SceneManager.MoveGameObjectToScene(ghostObj, simulationScene);
// Copy all the bricks to the simulated scene. These are stored under a parent Game Object that
// is attached in the editor
foreach (Transform obj in bricks.transform)
{
ghostObj = Instantiate(obj.gameObject, obj.position, obj.rotation);
ghostObj.GetComponent<SpriteRenderer>().enabled = false;
SceneManager.MoveGameObjectToScene(ghostObj, simulationScene);
}
// Copy the top, left, and right walls to the simulated scene. These are invisible and don't have sprites.
// These are stored under a parent Game Object that is attached in the editor
foreach (Transform obj in walls.transform)
{
ghostObj = Instantiate(obj.gameObject, obj.position, obj.rotation);
SceneManager.MoveGameObjectToScene(ghostObj, simulationScene);
}
} // CreatePhysicsScene
private void DrawTrajectory()
{
// Get the starting Screen position of the gun from the World position
gunPosScreenV3 = cam.WorldToScreenPoint(gun.transform.position);
gunPosScreenV3.z = 1;
// Get position of mouse in screen units
aimPointScreenV3 = Input.mousePosition;
// Get the position of the mouse in world units for aiming
aimPointWorldV3 = cam.ScreenToWorldPoint(aimPointScreenV3);
aimPointWorldV3.z = 1;
// Calculate the normalized direction of the aim point compared to the gun
aimDirectionV3 = (aimPointScreenV3 - gunPosScreenV3).normalized;
Physics2D.simulationMode = SimulationMode2D.Script;
// Instantiate the ball prefab for the simulation
ghostObj = Instantiate(ballPrefab, gun.transform.position, Quaternion.identity);
// Assign the ball's velocity
ballDirection = new Vector2(aimDirectionV3.x, aimDirectionV3.y);
ballVelocity = ballDirection * 20f;
ghostObj.GetComponent<Rigidbody2D>().velocity = ballVelocity;
SceneManager.MoveGameObjectToScene(ghostObj.gameObject, simulationScene);
lr.positionCount = maxPhysicsFrameIterations;
for (var i = 0; i < maxPhysicsFrameIterations; i++)
{
physicsScene.Simulate(Time.fixedDeltaTime);
//Physics2D.Simulate(Time.fixedDeltaTime);
lr.SetPosition(i, ghostObj.transform.position);
}
Destroy(ghostObj);
Physics2D.simulationMode = SimulationMode2D.Update;
} // DrawTrajectory
}
您使用了 aimPointScreenV3,但它似乎从来没有 initialized/calculated。
找到答案了。只需要在 将球移动到模拟场景后 添加速度。
SceneManager.MoveGameObjectToScene(ghostObj.gameObject, simulationScene);
ghostObj.GetComponent<Rigidbody2D>().velocity = ballVelocity;