- Home /
Raycast that follows rotation when adding a new vector 3
EDIT: Here is a gif that helps visualize what I am trying to achieve.
As you can see my hands snap to the ledge whenever the raycast detects an object. However when I rotate my character the raycasts don't stay in front of my character meaning I can only snap from 1 specific rotation.
So I've been searching online everywhere but it seems my specific problem I can't solve on my own.
I am making a raycast to determine when a 3d character controller has detected a ledge and can grab it. So I made a raycast that has a specific position (in front of the player and facing down). Yet now I am trying to get the raycast to always stay in front of my character rather than statically stay in the same position (rotate along with my character).
I don't know how to place a raycast in a specific position without using Vector 3. I feel like the problem could be in the direction.
Here's what I have so far (you can easily copy/paste this and it should work instantly):
//bools that will be triggered by hands raycast
public bool leftHandIK;
public bool rightHandIK;
//to move hands to ledge
public Vector3 leftHandPosition;
public Vector3 rightHandPosition;
//to ensure hands don't go inside wall/ledges
public Vector3 leftHandOffset;
public Vector3 rightHandOffset;
//to make hands properly rotate alongside ledge
public Quaternion leftHandRotation;
public Quaternion rightHandRotation;
void FixedUpdate () {
RaycastHit lHit;
RaycastHit rHit;
//LeftHand IK check
//set a raycast at our location, add so the raycast starts just above our head + a little forward & casts it downwards & move that raycast to the left side
//if the leftside raycast hits something...
if(Physics.Raycast (transform.position + new Vector3(0.0f, 2.0f, 1f), -transform.up + new Vector3 (-0.5f, 0.0f, 0.0f), out lHit, 1f)){
leftHandIK = true;
leftHandPosition = lHit.point - leftHandOffset; //the position of the lhand is wherever the raycast hits - offset so we dont go inside walls/ledges
leftHandRotation = Quaternion.FromToRotation (Vector3.forward, lHit.normal); //this somehow calculates an appopropriate rotation for our hand
}else{
leftHandIK = false; //else lHandIK is not detecting anything
}
//RightHand IK check
if(Physics.Raycast (transform.position + new Vector3 (0.0f, 2.0f, 1f), -transform.up + new Vector3 (0.5f, 0f, 0f), out rHit, 1f)){
rightHandIK = true;
rightHandPosition = rHit.point - rightHandOffset;
rightHandRotation = Quaternion.FromToRotation (Vector3.forward, rHit.normal);
}else{
rightHandIK = false;
}
}
void Update () {
//Lefthand IK ray drawn
Debug.DrawRay (transform.position + new Vector3 (0.0f, 2.0f, 1f), -transform.up + new Vector3 (-0.5f, 0.0f, 0.0f), Color.green);
//Righthand IK ray drawn
Debug.DrawRay (transform.position + new Vector3 (0.0f, 2.0f, 1f), -transform.up + new Vector3 (0.5f, 0.0f, 0.0f), Color.green);
}
Whew, several days and attempts later and it appears I still have not figured out a way how to get the effect I am looking for. If anyone has any ideas please help!
Hm, I tried using transform point to add my local position to a world vector but it just breaks the racyast.
if(Physics.Raycast (transform.TransformPoint(transform.localPosition + vectorConstant), transform.TransformPoint(-Vector3.up + vectorConstant2), out lHit, 1f)){
You can see how one of my green raycast lines breaks off and remains in the constant vector (world space) and the other still does not manage to stay directly in front of my player. I did not apply this to the foot raycasts (red lines) so ignore those.
EDIT: I also seem to lose the I$$anonymous$$ snapping that I had with my characters oddly enough.
Ok I must have written it somewhere wrong but I've made big progress!
The raycasts now rotate along with my player! The bad news is that it very quickly gets out of control, acting erratically and either stretching massively or rotating along a different direction of the player. It never behaves the same way.
Here is a gif demonstrating some of the weird behaviour:
If I jump the raycasts points upward. I think whats happening is that its also getting my movement of going up/left/right. However if I stay absolutely still and ONLY rotate left right it works exactly how I want it to. It only breaks when I begin moving/jumping.
I think now what I need to do is figure out a way to get the localDirection to "freeze". I tried this by simply removing transformpoint in the direction but that does not seem to have worked out so well.
Ah, good! Since the problem occurs now when moving only, can we seen that code too? In particular, I would like to confirm that you are adjusting the chracater's world-position, rather than it's localPosition, when moving it.
This is what I'm doing
//constant vector variables (to deter$$anonymous$$e location/direction)
public Vector3 vectorConstant = new Vector3 (0.0f, 2.0f, 1f);
public Vector3 vectorConstant2 = new Vector3 (-0.5f, 0.0f, 0.0f);
public Vector3 vectorConstant3 = new Vector3 (0.5f, 0.0f, 0.0f);
//left hand I$$anonymous$$ check
if(Physics.Raycast (transform.TransformPoint(transform.localPosition + vectorConstant), transform.TransformPoint(-Vector3.up + vectorConstant2), out lHit, 1f))
//right hand I$$anonymous$$ check
if(Physics.Raycast (transform.TransformPoint(transform.localPosition + vectorConstant), transform.TransformPoint(-Vector3.up + vectorConstant3), out rHit, 1f)){
//draw left hand raycast
Debug.DrawRay (transform.TransformPoint(transform.localPosition + vectorConstant), transform.TransformPoint(-Vector3.up + vectorConstant2), Color.green);
//draw right hand raycast
Debug.DrawRay (transform.TransformPoint (transform.localPosition + vectorConstant), transform.TransformPoint (-Vector3.up + vectorConstant3), Color.green);
I tried using your code (below) but the same problem appears.
Vector3 Raypoint1= transform.TransformPoint(vectorConstant);
Vector3 Raypoint2= transform.TransformPoint(-Vector3.up+vectorConstant2);
Debug.DrawRay (Raypoint1,Raypoint2, Color.green);
Ok, something unexpected appears to be happening. Let's start by confir$$anonymous$$g the transform that we are using here is the same one that is adjusted when you move. Perhaps we should also look at the code that shows how you actualy move the character.
I'm not sure I fully understand what you mean by this
Let's start by confir$$anonymous$$g the transform that we are using here is the same one that is adjusted when you move
As for the movement code I would have never thought about that! I'm using a basic character controller only slightly modified the gravity. How I do movement is through the animator. I basically used a walking/run animation that goes on a slider from 0-1 and make a playerspeed. Then I blend between my walk and run if I hold all the way up on an analog stick, on keyboard it will just automatically go from my idle animation to run.
I'll look into seeing if my movement code has anything to do with that.
Here is a link to the full character controller:
This is beco$$anonymous$$g quite the adventure.
I have a feeling that it could be the movement script after all. Below is what I am using for my movement and I think transform.TransformDirection is causing the problem. Why this weird glitch also works with rigidbody I'm not entirely sure.
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
}
Answer by Glurth · Jun 15, 2016 at 04:50 PM
I'm not quite clear where you are getting stuck, let me know if this helps at all:
If you want a location Vector3, that is offset in "FRONT/SIDE/ARBITRARY OFFSET" of an object (where "front" is based on the objects rotation), you can simply use the Transform function TransformPoint: https://docs.unity3d.com/ScriptReference/Transform.TransformPoint.html;
Vector3 localOffset = new Vector3(0,2,1);
Vector3 worldOffset= transform.TransformPoint(localOffset);
Alternatively, you could create an empty game object as a child of the character, at the offset you want. This objects local offset will remain constant, but it's world position will be automatically transformed by it's parent (the character object). You can then reference this object's transform.position for your raycast start.
Edit: Sorry I wasn't clear. When you do your raycast you are adding transform.position plus some constant vector.
transform.position + new Vector3 (0.0f, 2.0f, 1f)
-transform.up + new Vector3 (-0.5f, 0.0f, 0.0f)
I suspect this is where you problem lies because you are adding a world-space coordinate to a model-space coordinate. Try adding the localPosition, rather than the (world)position to the constant vector. THEN transform to world coordinates e.g.:
TransformPoint(transform.localPosition + VectorConstant);
TransformPoint(-Vector3.up + VectorConstant2);
I usually have localPosition set to Vector3.Zero, in which case, the original example is equivalent to the last. My assumption, was of course, my mistake.
sorry for the late reply. Here is a gif that helps visualize what I am trying to achieve.
As you can see my hands snap to the ledge whenever the raycast detects an object. However when I rotate my character the raycasts don't stay in front of my character meaning I can only snap from 1 specific rotation.
$$anonymous$$aking an empty child makes me lose the ik Snap effect I want to achieve on top of that it seems that it wouldn't rotate alongside my character anyways. Transformpoint seems to also not really do what I want to achieve.
I set the position so I feel that specifically setting its location is what causes it to remain static yet without it I won't be able to properly check for ledges.
EDIT: I'm currently experimenting with InverseTransformPoint to see if this will solve the issue but am not sure if this is the right track.