I have a 2D brick breaker style game in Unity where you get to choose the angle of your shot before each turn with the mouse. I'd like to show an accurate trajectory prediction of what a ball will do while the player is aiming, up to maybe 200 frames of ball movement (for now). This involves potentially bouncing off the top, left, and right walls, and any bricks.
I'm using a physics simulation and line renderer to accomplish this but can't get it to work correctly.
It's supposed to copy the gun, walls, and bricks into a virtual Scene, launch a ball in the angle the player is aiming, simulate 200 frames of movement, and plot those in a line renderer.
Here is an abridged version of the game code, reduced to just focus on the aiming and physics simulation for the 1st turn. When I run it, it simply plots the 200 points of the line renderer in the same coordinates as the gun.
What am I doing wrong? Thank you!
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
}
CodePudding user response:
You use aimPointScreenV3 but it appears to never be initialized/calculated.
CodePudding user response:
Found the answer. Just needed to add the velocity to the ball after moving it to the simulated scene.
SceneManager.MoveGameObjectToScene(ghostObj.gameObject, simulationScene);
ghostObj.GetComponent<Rigidbody2D>().velocity = ballVelocity;