Hi, I am trying to make a small script so my character can walk on a highwire.
But I have a problem when the character is ON the highwire, I can’t seem to get him positioned in the middle of the wire.
I want the player to be in the middle of the highwire as the picture shows, I have no problems figuring out when he is on the highwire, and I can access the highwires transform.
The diagram is clear, but I’m not quite sure if you’ve already written the code and it’s not working as expected, or if you’re asking how to write the code in the first place.
One option would be to make the character a child object of the wire while the character is on the wire, and then move the character in local space during that time (e.g. along one of the cardinal axes).
If you want to keep the character in global space though, the same effect can be achieved; you’ll just have to move the character in ‘virtual local space’ or parametric space or something, and then transform the ‘virtual’ position into world space.
(In either case, the details will depend somewhat on how you want the controls to work while the character is on the wire.)
var charController : CharacterController;
function WalkingOnWire()
{
var forwardPressed: boolean = Input.GetButton("Forward");
var backwardPressed: boolean = Input.GetButton("Backward");
if(forwardPressed backwardPressed) ; //both pressed, not going anywhere
else if(forwardPressed) charController.Move(transform.forward);
else if(backwardPressed) charController.Move(-transform.forward);
else ; // nothing is pressed
}
//There is a small invisible box ontop of the wire, it is as long as the wire, so while I am in that box, i will be highWireWalking
function LandedOnWire(wireCollider : Collider)
{
//the angle between my players facing direction and the wire
var angleBetween = wireCollider.transform.rotation.eulerAngles.y - transform.rotation.eulerAngles.y;
//When landing on the vire we have to be sure we are facing the same way as the wire, cannot go left or write on the small wire
transform.rotation = wireCollider.transform.rotation;
if(( angleBetween<270 angleBetween>90) || (angleBetween<-90 angleBetween>-270)){
transform.Rotate(0,180,0);
}
//Fix the player to the middle of the wire
//----??????-----
//----HELP-----
//----??????-----
}
Each method will be called when needed, all i need is that calculation to fix the player in the middle of the wire =)
Anyway, maybe that compiles in UnityScript (the equivalent code doesn’t compile in C#), so I’ll just assume it does what you intend it to do
One way to ‘attach’ the player to the wire is to move the player to the closest point on the wire to the player’s current position. This is trivial, and I can show you how to do it if you can provide a little more info.
Specifically, how is the wire oriented and positioned in local space? Is it centered at the transform position and aligned with one of the transform’s local axes? How is its length or extent specified?
Ok, I can’t remember off the top of my head if the default Unity cube is 1x1x1 or 2x2x2, but you can check that easily enough. In any case, what you’ll need is the wire’s half-length, or ‘extent’.
First you’ll need a closest-point-on-segment function. Here it is in C# (you can convert it to UnityScript if needed). This will just be typed into the post, so let me know if it doesn’t work as expected or if there are compilation errors:
Vector3 ClosestPointOnSegment(Vector3 p, Vector3 p1, Vector3 p2)
{
Vector3 diff = p - p1;
Vector3 direction = p2 - p1;
float t = Vector3.Dot(diff, direction) / Vector3.Dot(direction, direction);
t = Mathf.Clamp01(t);
return p1 + t * direction;
}
To use this function, you’d submit the character’s current position for ‘p’, and the endpoints of the wire for p1 and p2. One way to compute these endpoints is as follows (where ‘transform’ is the transform of the wire object):
The point it calculated were the position where player should stand on, not the character position, ^^ looks funny when the charater got a wire through him.