- Home /
Raycast and OnTriggerEnter performance
Hi.
I have several small objects the player (FPS) can interact with. Examples:
a door and the player can interact with the doorknob to open the door
a machine with a button on it to power on the machine
a weapon on the ground to pick it up
I shoot a raycast from the players view to check if the player is looking at the object
What is best performance wise:
1) Constantly shoot the raycast?
2) Have a OnTriggerEnter on every interactive object and shoot a raycast only when the player enters the trigger?
$$anonymous$$y guess is you are pressing a button to interact correct? Even better than 1 and 2 is to cast a ray only when the "Interact" button is pressed and do a check from there as to what the player has interacted with
with this method you arent constantly casting unnecessary rays and you dont have to calculate trigger collisions other than the "Interaction raycast"
If you are looking for a system where a UI element will pop up and tell the player "Open door", "Press button", etc wisearn is right, #2 would be best.
There is indeed a UI element that tell the player that he can interact with the object if he is not to far away from it.
$$anonymous$$y guess was also the #2 would be the best to do. But I was not sure if "OnTriggerEnter" would use a lot of performance compared with a constant raycast. But you probably need a lot of "OnTriggerEnter" in scene to have performance issues with it.
Thanks for the answers.
Answer by robertbu · Oct 20, 2014 at 04:46 PM
I believe you are putting your performance efforts in the wrong place. Colliders or Raycasts are pretty efficient. They are the backbone of many apps. When I have these kinds of questions, I run a test to see what I get. So here is a basic FPS script:
#pragma strict
private var data : float[] = new float[160];
private var i = 0;
private var fps : int;
function Update () {
data[i] = Time.time;
i = (i + 1) % data.Length;
fps = 0;
for (var j = 0; j < data.Length; j++) {
if (data[j] > 0 && data[j] >= Time.time - 1.0)
fps++;
}
}
function OnGUI() {
GUI.Label(Rect(10,10,100,50), fps.ToString());
}
And here is a test script. It creates a set of planes and then Raycasts() against those planes. The spacebar doubles the number of Raycasts().
#pragma strict
private var casts = 1;
private var planes = 200;
function Start() {
for (var i = 0; i < planes; i++) {
var go = GameObject.CreatePrimitive(PrimitiveType.Plane);
go.AddComponent.<MeshCollider>();
go.transform.rotation = Random.rotation;
go.transform.position = Random.insideUnitSphere * 10.0;
}
}
function Update () {
var hit : RaycastHit;
for (var i = 0; i < casts; i++) {
Physics.Raycast(transform.position, Random.onUnitSphere, hit);
}
if (Input.GetKeyDown(KeyCode.Space)) {
casts *= 2;
}
}
function OnGUI() {
GUI.Label(Rect(10,60,50,100), casts.ToString());
}
Put both scripts on an empty game object or the camera and hit play. Start hitting the space bar to increase (double) the number of casts. See when you get an FPS drop. For me in the editor, it was 2048 casts when I first see a drop, but for an accurate test, you would want to use object representative of the complexity you have in your game, and you would want to run on the target device. But my point is, that one continuous Raycast() is not a big deal.
And if you ended up with enough raycasts and/or objects for raycasting to become a problem, then there are ways to mitigate the issue.
Make sure you have the objects that you want to detect on their own layer and use a layer mask in the Raycast().
Use a distance check to avoid raycasting when nothing is in range.
Use an angle check to make sure the player can 'see' the object
The Unity Wiki also has an FPS script:
Your answer
Follow this Question
Related Questions
Pick up game objects with cursor (raycasting) 1 Answer
How to turn real life object into gameobject 1 Answer
Yet another collision detection mystery 1 Answer
Cannot interact with image? 0 Answers
Terminal Typing 0 Answers