Need help with GameObject placement
What I'm trying to do here is to place a GameObject seed on the ground infront of the player on the ground, but I get weird results; When I jump, it gets placed in the air and so on..
How can I get it to always be placed on the terrain infront of the player / where the player is looking?
What I tried was to subtract 1 from playerPosition.y and add 1 to playerPosition.z but that didn't help much at all.
Here's my code:
using UnityEngine;
using System.Collections;
public class PlaceSeeds : MonoBehaviour {
// Use Player GameObject
public GameObject player;
// Use a seed model
public GameObject seedToPlaceModel;
private Vector3 objectSpawnPosition;
private Vector3 playerPosition;
// Update is called once per frame
void Update () {
playerPosition = player.transform.position;
objectSpawnPosition = new Vector3 (playerPosition.x, playerPosition.y, playerPosition.z);
// If we leftclick (Mousebutton)
if (Input.GetKeyDown (KeyCode.Mouse0)) {
Instantiate (seedToPlaceModel, objectSpawnPosition, Quaternion.identity);
}
}
}
Answer by ThomLaurent · Sep 15, 2016 at 02:03 PM
What you are looking for is the Physics.Raycast()
function ( see doc ) :
Physics.Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
To be used like this:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
float maxDistance = 100; // in Unity units
if (Physics.Raycast(ray, out hit, maxDistance))
{
Debug.Log("The mouse hit a collider at " + hit.point);
// Draw a line to see the ray
Debug.DrawLine(ray.origin, hit.point);
}
Note you can use the layerMask
parameter to only hit terrains instances by placing each of your terrains in a specific layer
Hi, thanks for the guidance. I got it somewhat working, I checked all layers that are not used except "Terrain" layer, but now all trees spawn in the exact same position.
It also didn't spawn infront of me when placing them.
Code:
using UnityEngine;
using System.Collections;
public class PlaceSeeds : $$anonymous$$onoBehaviour {
// The range of the weapon
public float placementRange;
// Debug
public bool debugRay = false;
// Use the Camera FPSCamera
public Camera FPSCamera;
public Layer$$anonymous$$ask checkIgnoreLayers;
// Use a seed model
public GameObject seedToPlace$$anonymous$$odel;
private Vector3 objectSpawnPosition;
private Vector3 playerPosition;
// Update is called once per frame
void Update () {
// Ray in the middle of the screen, centered
Ray ray = FPSCamera.ScreenPointToRay (Input.mousePosition);
RaycastHit hitInfo;
objectSpawnPosition = new Vector3 (playerPosition.x, playerPosition.y, playerPosition.z);
// If we leftclick ($$anonymous$$ousebutton)
if (Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.$$anonymous$$ouse0)) {
if (Physics.Raycast (ray, out hitInfo, placementRange, checkIgnoreLayers, QueryTriggerInteraction.UseGlobal)) {
// Instantiate (Spawn) the seedToPlace$$anonymous$$odel to terrain (checkIgnoreLayers) only
Instantiate (seedToPlace$$anonymous$$odel, objectSpawnPosition, Quaternion.identity);
// What GameObject the seed spawned
Debug.Log ("Player planted a " + seedToPlace$$anonymous$$odel.name);
}
}
}
}
That's normal, in your code you set your object position to objectSpawnPosition
which is a copy of playerPosition
. Since it's a private field I suppose it runs Vector3.zero
Oh, you're right. I missed that.
I removed playerPosition variable and switched that part in the Update() function to say:
objectSpawnPosition = transform.position;
It sorta works. The GameObject spawn floating in the air and "ignores" the terrain. I doublechecked the layers being ignored and it's still correct as only Terrain layer is checked.
I think I now understand what you're ai$$anonymous$$g for, does this code works for you?
public class PlaceSeeds : $$anonymous$$onoBehaviour {
// The range of the weapon
public float placementRange;
// Use the Camera FPSCamera
public Camera FPSCamera;
public Layer$$anonymous$$ask checkIgnoreLayers;
// Use a seed model
public GameObject seedToPlace$$anonymous$$odel;
// Update is called once per frame
void Update () {
// Ray in the middle of the screen, centered
Vector3 direction = new Vector3(0, -1, placementRange);
Ray ray = new Ray(FPSCamera.transform.position, FPSCamera.transform.rotation * direction);
RaycastHit hitInfo;
// If we leftclick ($$anonymous$$ousebutton)
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.$$anonymous$$ouse0)) {
if (Physics.Raycast(ray, out hitInfo, direction.magnitude, checkIgnoreLayers, QueryTriggerInteraction.UseGlobal)) {
// Instantiate (Spawn) the seedToPlace$$anonymous$$odel to terrain (checkIgnoreLayers) only
Instantiate(seedToPlace$$anonymous$$odel, hitInfo.point, Quaternion.identity);
// What GameObject the seed spawned
Debug.Log("Player planted a " + seedToPlace$$anonymous$$odel.name);
}
}
}
}
It is! This is exactly what I was trying to do, thank you @ThomLaurent! :)
Answer by DanielArkham · Sep 15, 2016 at 02:06 PM
First, are you making a FPS game, or something like that? If that is the case, what you can do is to create an empty object, attach it to the Camera of the FPS Player Prefab and put the object in front of the camera.
Your answer
Follow this Question
Related Questions
How to Parent a Camera to the Head Bone with No Camera Shake? 0 Answers
Place GameObject on terrain even if player is looking up 2 Answers
Status Effect Help 0 Answers
how do i get my player get sucked into a gameobject 2 Answers
Launch Pad Issues 1 Answer