- Home /
Using Raycasts to change the X and Y position of a moving GameObject?
Hi, so first off, to give a little background, I'm a student and have been trying to teach myself Unity for the past year...and it's been going fairly well! However, a lot of what I've made so far are prototypes and now I'm working on my first somewhat original concept.
The idea is that you're controlling a spaceship as it continually goes down a set track (I'm using Cinemachine's Dolly Track with Cart to handle that aspect of the game). The most basic gameplay element is that while your spaceship is moving along the track, you can use WASD to shift your local x and y position by a certain value within a kind of 3x3 grid square. So you start in the middle of the center grid square, and depending on which key (or combination of keys with diagonals) you hit you would shift your position smoothly to the center of the grid square in that respective direction.
I was actually able to figure out how to perform this movement in a way, even if its not the cleanest code, by shooting Raycasts in a direction upon a key press, seeing if it hit the collider of a GameObject with the tag "MovementPoint" and then using the Lerp function to move the Player. Both the 9 GameObjects with the tags "MovementPoint" and the Player are a child of the Cinemachine Cart:
[Header("Set in Inspector")]
public float xySpeed = 20f; // The player's speed when shifting.
public float forwardSpeed = 50f; // The player's speed when moving forward along the Z axis.
[Header("Public References")]
public CinemachineDollyCart dollyCart;
public Transform cameraParent;
[Header("Set Dynamically")]
// The center in X and Y coordinates of the current grid square.
private float centerX = 0;
private float centerY = 20;
[Header("Remain Constant")]
private float sideLength = 15; // The length of each side of a grid square.
private void Start()
{
// The player's localPosition is set to the center of the middle grid square.
transform.localPosition = new Vector3(centerX, centerY, 0);
}
private void Update()
{
// Call to the LocalMove() method which handles the basic player movement.
LocalMove();
}
private void LocalMove()
{
RaycastHit hit;
// If W is pressed.
if (Input.GetKeyDown(KeyCode.W) && isLocked == false)
{
if (Physics.Raycast(transform.localPosition, transform.TransformDirection(Vector3.up), out hit, 15f))
{
if (hit.collider.gameObject.CompareTag("MovementPoint"))
{
centerY += sideLength;
}
}
}
// If S is pressed.
if (Input.GetKeyDown(KeyCode.S) && isLocked == false)
{
if (Physics.Raycast(transform.localPosition, transform.TransformDirection(Vector3.down), out hit, 15f))
{
if (hit.collider.gameObject.CompareTag("MovementPoint"))
{
centerY -= sideLength;
}
}
}
// If A is pressed.
if (Input.GetKeyDown(KeyCode.A) && isLocked == false)
{
if (Physics.Raycast(transform.localPosition, transform.TransformDirection(Vector3.left), out hit, 15f))
{
if (hit.collider.gameObject.CompareTag("MovementPoint"))
{
centerX -= sideLength;
}
}
}
// If D is pressed.
if (Input.GetKeyDown(KeyCode.D) && isLocked == false)
{
if (Physics.Raycast(transform.localPosition, transform.TransformDirection(Vector3.right), out hit, 15f))
{
if (hit.collider.gameObject.CompareTag("MovementPoint"))
{
centerX += sideLength;
}
}
}
// Change the player's localPosition based on the newly set values.
transform.localPosition = Vector3.Lerp(transform.localPosition, new Vector3(centerX, centerY, transform.localPosition.z), xySpeed * Time.deltaTime);
}
However, while this works when the player is still...if I change the Cinemachine Cart's speed to anything higher than 0, while it appears like the colliders of the movement points are moving in the Scene View...I can't move the player at all unless I make the colliders super long, and even then it seems like they're not moving with their GameObjects. Is there any way to have Physics update the position of the colliders to match that of their GameObjects so that even if they're consistently moving they can be hit by raycasts? Or is there a better way to do this? Sorry for the giant block, this is my first post.
Physics.Raycast takes a world position. Passing a local position will ins$$anonymous$$d cast it as if the object's local space was centered on the world.
Answer by GrayLightGames · Oct 18, 2019 at 04:19 PM
Hi @MysticDan, so if I'm reading you right, 3d space that the ship is navigating correct? I'm unclear how you move in the z direction, but for xy it sounds like you're navigating a 2d plane with WASD, right? I'm assuming that the ship is a child of the plane and the plane is moving relative to the level. One option would be you can create 4 single point GameObjects on the plane and use MoveTowards. So if w is pressed, you would call something like:
ship.transform.localPosition = MoveTowards(ship.transform.localPosition, upObject.transform.transform.localPosition, xySpeed * Time.deltaTime);
Given that multiple keys can be pressed, you may want to use a Vector3 variable initialized to Vector3.zero to combine the move operations and then set the localPosition to be the result. Just so the ship is only repositioned once per cycle... but even if you just reposition on key press, it should work simpler than the raycast option you're trying. You can do something similar if you have z movement with 2 more GameObjects on the z axis. Hope that helps!
Hey! I'm sorry for not responding sooner, but your answer helped me a lot. I ended up changing my movement method from Raycasts to a 2-D Array of GameObjects called Points. Basically, on WASD input I executed a nested for-loop(for each respective key), that would go through my array, deter$$anonymous$$e what Point I was currently at, and set a GameObject variable called newPoint to the element of my array that was either below, above, or to my currentPoint's sides. I then used $$anonymous$$oveTowards to move from my currentPoint to the newPoint if it was set.
Great, glad I could help, and glad you got it working. Good luck with your project!
Your answer
Follow this Question
Related Questions
FIXED: How can I stop a collider from tunneling? 2 Answers
Simple Movement Game: Physics vs Manual Collision Detection? 2 Answers
Problem with custom raycast2D collision detection system. 1 Answer
Collision normals changing based on player position 0 Answers
Collision Issue - Walk Through Object 0 Answers