Reputation: 593
I'm building to WebGL and have disabled the physics system in Package Manager to reduce build size. I'm now in a position where I want to find where on a plane a raycast fired from the cursor, lands. See diagram:
Can I do this without the physics system, or will I be required to include it and the couple of mb it adds to the current build size of 5mb?
Upvotes: 0
Views: 1049
Reputation: 90679
You could use a Plane.Raycast
using UnityEngine;
public class GetRaycast : MonoBehaviour
{
Camera camera;
public Transform PlaneTransform;
public Transform Player;
// Start is called before the first frame update
private void Start()
{
camera = Camera.main;
}
// Update is called once per frame
private void Update()
{
if (!Input.GetMouseButtonDown(0)) return;
// you just need any 3 points inside of the plane and provide them
// in clockwise order (so the normal points upwards)
// for the raycast this actually wouldn't matter
var plane = new Plane(PlaneTransform.position, PlaneTransform.position + PlaneTransform.forward, PlaneTransform.position + PlaneTransform.right);
// get ray for mouseposition
var ray = camera.ScreenPointToRay(Input.mousePosition);
// enter will be the distance between the ray origin and the hit plane
if (!plane.Raycast(ray, out var enter)) return;
// GetPoint returns the position along the raycast in
// the given distance from the ray origin
Player.position = ray.GetPoint(enter) + Vector3.up * 0.1f;
}
}
However, a huge disadvantage of this method however is that the generated plane
is infinite so the raycast detection doesn't end at the limits of the actual plane so you would have to clamp that "manually" again.
You could do this in this simple example where the plane is flat in the world like
public class GetRaycast : MonoBehaviour
{
Camera camera;
public MeshFilter PlaneTransform;
public Transform Player;
// Start is called before the first frame update
private void Start()
{
camera = Camera.main;
}
// Update is called once per frame
private void Update()
{
if (!Input.GetMouseButtonDown(0)) return;
// you just need any 3 points inside of the plane and provide them
// in clockwise order (so the normal points upwards)
// for the raycast this actually wouldn't matter
var plane = new Plane(PlaneTransform.transform.position, PlaneTransform.transform.position + PlaneTransform.transform.forward, PlaneTransform.transform.position + PlaneTransform.transform.right);
// get ray for mouseposition
var ray = camera.ScreenPointToRay(Input.mousePosition);
// enter will be the distance between the ray origin and the hit plane
if (!plane.Raycast(ray, out var enter)) return;
// GetPoint returns the position along the raycast in
// the given distance from the ray origin
var hitPosition = ray.GetPoint(enter);
// check if hitposition is within the Plane mesh
// mesh.bounds returns the bounding box of the mesh but
// unscaled. lossyScale is the overall scale in the scene
// also taking all parent scales into account
if (hitPosition.x < PlaneTransform.mesh.bounds.min.x * PlaneTransform.transform.lossyScale.x
|| hitPosition.x > PlaneTransform.mesh.bounds.max.x * PlaneTransform.transform.lossyScale.x
|| hitPosition.z < PlaneTransform.mesh.bounds.min.z * PlaneTransform.transform.lossyScale.z
|| hitPosition.z > PlaneTransform.mesh.bounds.max.z * PlaneTransform.transform.lossyScale.z)
{
return;
}
Player.position = hitPosition + Vector3.up * 0.1f;
}
}
Now the player should only get set to the new position if the click was inside of the Plane.
Originally I thought you deactivated the Physics package which is experimental and is more about rigidbody and mass collisions. And not related to Physics.Raycast
which is part of the UnityEngine
.
After your comment I understand you actually deactivate the Built-In Physics
.
Otherwise you still would be able to simply use Physics.Raycast
like e.g.
using UnityEngine;
public class GetRaycast : MonoBehaviour
{
Camera camera;
public Transform Player;
// Start is called before the first frame update
private void Start()
{
camera = Camera.main;
}
// Update is called once per frame
private void Update()
{
if (!Input.GetMouseButtonDown(0)) return;
if (!Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out var hit)) return;
// I just make it float a little to avoid mesh overlaps
Player.position = hit.point + Vector3.up * 0.1f;
}
}
Upvotes: 3