playMaker

Author Topic: Ray cast from screen space  (Read 6637 times)

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 14121
  • Official Playmaker Support
    • View Profile
Ray cast from screen space
« on: January 10, 2013, 11:58:02 PM »
Hi,

 Following some thread, I created a new raycast action to ray cast from the screen space ( from the mouse position or touch position). There are actions like mouse Pick, but it doesn't work for touches. and Here you have control over the screen position, so it can be anything, even arbitrary positions.


Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Physics)]
[Tooltip("Casts a Ray against all Colliders in the scene from the screenSpace. Use a Vector3 screen position as the origin of the ray. Use GetRaycastInfo to get more detailed info.")]
public class RaycastFromScreen : FsmStateAction
{
[Tooltip("The Camera GameObject. Leave to none to use the main camera")]
[CheckForComponent(typeof(Camera))]
public FsmOwnerDefault camera;

[Tooltip("Start ray at a vector3 screen position. Screenspace is defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight). ")]
public FsmVector3 fromScreenPosition;

[Tooltip("The length of the ray. Set to -1 for infinity.")]
public FsmFloat distance;

[Tooltip("Event to send if the ray hits an object.")]
[UIHint(UIHint.Variable)]
public FsmEvent hitEvent;

[Tooltip("Set a bool variable to true if hit something, otherwise false.")]
[UIHint(UIHint.Variable)]
public FsmBool storeDidHit;

[Tooltip("Store the game object hit in a variable.")]
[UIHint(UIHint.Variable)]
public FsmGameObject storeHitObject;

[Tooltip("Set how often to cast a ray. 0 = once, don't repeat; 1 = everyFrame; 2 = every other frame... \nSince raycasts can get expensive use the highest repeat interval you can get away with.")]
public FsmInt repeatInterval;

[UIHint(UIHint.Layer)]
[Tooltip("Pick only from these layers.")]
public FsmInt[] layerMask;

[Tooltip("Invert the mask, so you pick from all layers except those defined above.")]
public FsmBool invertMask;

int repeat;

private Camera _cam;

public override void Reset()
{

camera =  new FsmOwnerDefault() { OwnerOption = OwnerDefaultOption.SpecifyGameObject};
camera.GameObject.UseVariable = true;

fromScreenPosition = new FsmVector3 { UseVariable = true };
distance = 100;
hitEvent = null;
storeDidHit = null;
storeHitObject = null;
repeatInterval = 1;
layerMask = new FsmInt[0];
invertMask = false;
}

public override void OnEnter()
{


var go = Fsm.GetOwnerDefaultTarget(camera);
if (go == null)
{
_cam = Camera.mainCamera;
}else{

Camera _camera = go.camera;
if (_camera == null)
{
LogError("Missing Camera Component!");
Finish();
return;
}else{
_cam = _camera;
}
}

DoRaycastFromScreen();

if (repeatInterval.Value == 0)
{
Finish();
}
}

public override void OnUpdate()
{
repeat--;

if (repeat == 0)
{
DoRaycastFromScreen();
}
}

void DoRaycastFromScreen()
{
repeat = repeatInterval.Value;

if (distance.Value == 0)
{
return;
}


var screenPos = fromScreenPosition.Value;

var rayLength = Mathf.Infinity;
if (distance.Value > 0 )
{
rayLength = distance.Value;
}


RaycastHit hitInfo;

Ray ray  = _cam.ScreenPointToRay(screenPos);
Physics.Raycast(ray,out hitInfo, rayLength, ActionHelpers.LayerArrayToLayerMask(layerMask, invertMask.Value));

Fsm.RaycastHitInfo = hitInfo;

bool didHit = hitInfo.collider != null;

storeDidHit.Value = didHit;

if (didHit)
{
storeHitObject.Value = hitInfo.collider.collider.gameObject;
Fsm.Event(hitEvent);
}
}
}
}

Bye,

 Jean

amaranth

  • Full Member
  • ***
  • Posts: 172
    • View Profile
Re: Ray cast from screen space
« Reply #1 on: January 23, 2013, 05:56:05 PM »
Thank you very much! I needed this today.

qholmes

  • 1.2 Beta
  • Hero Member
  • *
  • Posts: 509
    • View Profile
Re: Ray cast from screen space
« Reply #2 on: January 23, 2013, 10:14:18 PM »
Jean,

Why do you have Collider twice in this line?

storeHitObject.Value = hitInfo.collider.collider.gameObject;

I have been using the Screen Pick Action and have modified it to suit me but i can not get the GO reference back from the Raycast. I ran across this post which is very similar.. not sure what you did different from Screen Pick but anyway the only difference in the GO portion was the extra collider but it still does not work in my script?

Q

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 14121
  • Official Playmaker Support
    • View Profile
Re: Ray cast from screen space
« Reply #3 on: January 24, 2013, 07:27:31 AM »
hi,

 ignore the extra collider, ( you can remove the redundancy), it's simply some convenient two ways access within the Unity api, it should only access the collider once of course.

 what doesn't work with this action? I just tested it again and it works just fine.

bye,

 Jean

Khoa1994

  • Playmaker Newbie
  • *
  • Posts: 33
    • View Profile
Re: Ray cast from screen space
« Reply #4 on: June 25, 2014, 03:57:50 AM »
In my game, my camera move a round a big rectangular box. When I tap the rectangular box on the touch screen, I want to know where the raycast hit the rectangular box. I plan on using the "RaycastFromScreen" action to do so but don't know how.
Please help me.

Khoa1994

  • Playmaker Newbie
  • *
  • Posts: 33
    • View Profile
Re: Ray cast from screen space
« Reply #5 on: June 26, 2014, 10:45:33 PM »
I get 'RaycastFromScreen" to work. However, I don't understand why the parameter "From Screen Position" is a vector3. The screen is a 2-dimensional space. What should I set the z value for the "From Screen Position" to be? Should I set z to 0?
Also, I don't understand why I got different "distance" when my camera stays still and I click on different part of a plane.

Khoa1994

  • Playmaker Newbie
  • *
  • Posts: 33
    • View Profile
Re: Ray cast from screen space
« Reply #6 on: July 05, 2014, 10:58:19 AM »
Figured out how to use RaycastFromScreen.