- Home /
3rd person click to move; issues following terrain.
I have been combining various JavaScript code and sources form numerous sites. My code allows me to orbit the player with a right mouse click, and the move code for the player moves from current to the location provided from raycast/camera/terrain at mouse cursor even after letting off of the mouse button, the issue is rigidbody does not keep player on the ground and when on the ground player vibrates.
var dir : Vector3; var hit : RaycastHit ; var rot = 0; var k : Vector3; var speed : float = 10.0; var gravity : float = 5.0;
private var yourCharacterController : CharacterController;
function Start() { yourCharacterController = GetComponent(CharacterController); }
function FixedUpdate() {
if (Input.GetMouseButton(0)) { var ray = Camera.main.ScreenPointToRay(Input.mousePosition); Physics.Raycast(Camera.main.transform.position,ray.direction,hit,1000); hit.point.y += 0.1; dir = hit.point - transform.position;
var angle = Vector3.Angle(dir, transform.forward);
var k = Vector3.Cross(transform.forward, dir);
k.Normalize();
rot = k[1]*(angle*2.5);
transform.Rotate(Vector3.up*rot*Time.deltaTime*5);
yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);
print ("Transform Pos" + transform.position + "Dir" + dir.normalized + "Hitpoint" + hit.point);
}
else { // if not at clicked location continue moving there if (transform.position != hit.point) { dir = hit.point - transform.position;
angle = Vector3.Angle(dir, transform.forward);
k = Vector3.Cross(transform.forward, dir);
k.Normalize();
rot = k[1]*(angle*2.5);
transform.Rotate(Vector3.up*rot*Time.deltaTime*5);
yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);
print ("Transform Pos" + transform.position + "Dir" + dir.normalized + "Hitpoint" + hit.point);
}
}
}
function OnControllerColliderHit(collision: ControllerColliderHit) { if (collision.transform.tag != "ground") { transform.position.y -= gravity * Time.deltaTime; } }
Any help would be greatly appreciated.
Answer by Mike 3 · Jun 12, 2010 at 10:56 AM
You mention that you're using a rigidbody, but all your code points to you using a character controller object. Using both together is usually a very bad idea, though it's permissable if the rigidbody is set to kinematic (So that it's only used for collision response - though I'm not sure you need that here)
Secondly, I'd make sure that you don't apply any vertical motion to the character. Quickest way is to change this line
hit.point.y += 0.1;
to this
hit.point.y = transform.position.y;
Thirdly, the gravity part of your code just looks crazy - It only applies gravity when you're hitting an object which isn't the ground. I'd check how the first person controller script does gravity (it applies it every frame that you're not on the ground)
Answer by Kinenan · Jun 12, 2010 at 11:23 AM
Thanks Mike. I forgot I had that line of code in there, been trying everything under the sun for about 8 or more hours and finally found something almost flawless. The only slight issue is that now my player controlled object slips slightly under the terrain briefly now and again, which the CharacterController.move function should not push an object past a collision, so a little confused as to why it's happening. Other then that its great.
I went through and added the best comments I could for my level of understanding of the code. Also added layer masking to the ray cast so it only detects object in my "Walk Mesh" layer. I am going to move onto creating a minimal particle/projector to the location clicked, and a "No walk mesh" layer masking possibly incorporating a function to fade out the top of tall objects (think NWN). If anyone sees anywhere it can be improved please let me know.
var dir : Vector3; var k : Vector3; var hit : RaycastHit ; var rot = 0; var speed : float = 10.0; var gravity : float = -18.0;
private var layerMask : int = 1 << 9; private var gravityPower : Vector3 = Vector3.zero; private var yourCharacterController : CharacterController;
function Start() { yourCharacterController = GetComponent(CharacterController); gravityPower.y = gravity; }
function FixedUpdate() {
if (Input.GetMouseButton(0)) { // Cast ray from mouse to point on terrain and get location var ray = Camera.main.ScreenPointToRay(Input.mousePosition); Physics.Raycast(Camera.main.transform.position,ray.direction,hit, 1000,layerMask); //hit.point.y += 0.1;
// Define direction to move
dir = hit.point - transform.position;
// Get rotation smoothly
var angle = Vector3.Angle(dir, transform.forward);
var k = Vector3.Cross(transform.forward, dir);
k.Normalize();
rot = k[1]*(angle*2.5);
// ---- Move controller ---- //
// Apply Gravity
yourCharacterController.Move(gravityPower * Time.deltaTime);
// Apply Rotation
transform.Rotate(Vector3.up*rot*Time.deltaTime*5);
// Move towards direction (dir) normalized
yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);
// Debug check
print ("Transform Pos" + transform.position + "Dir" + dir.normalized + "Hitpoint" + hit.point);
}
else { // if not at clicked location continue moving there if (transform.position != hit.point) { // Define direction to move dir = hit.point - transform.position; // Get rotation smoothly angle = Vector3.Angle(dir, transform.forward); k = Vector3.Cross(transform.forward, dir); k.Normalize(); rot = k[1]*(angle*2.5);
// Move controller
// Apply Gravity
yourCharacterController.Move(gravityPower * Time.deltaTime);
// Apply Rotation
transform.Rotate(Vector3.up*rot*Time.deltaTime*5);
// Move towards direction (dir) normalized
yourCharacterController.Move(dir.normalized * Time.deltaTime * speed);
// Debug check
print ("gravityPower" + gravityPower.y);
}
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613061935im_/https://answers.unity.com/themes/thub/images/avi.jpg)