- Home /
Another question about Skyroads-like moving
A few months ago I asked about how to make a character move the way you did in Skyroads. (Old DOS game) The way it works is this: You have a min speed and a max speed, say 0 and 100. If you press UP (or the equivalent) it increases the speed and you go faster. Press DOWN and your speed decreases. You can never move "back" or "forward". Essentially, you are just controlling how fast your character moves. You have no real direct control over "moving" forward/backward.
Anyway, someone answered me on here and I got a nice simple script. I'm still new to scripting (I use JavaScript) and recently started work back up on my Skyroads-clone game. The method that the previous answer gave me uses transform.translate and that does not detect collisions, and is a very simple way to move. Since then I've gone over to using a CharacterController, and am having trouble getting my ship to behave like it's supposed to. Everything I try is always sloppy and doesn't come out right. So anyway, TL;DR, I am wondering if someone could shed some light here and tell me how exactly I would go about doing this. My old script (the simple one) is below, and after that I have the current CharacterController script I'm using.
I don't necessarily want you to write me up a script that I can copy+paste with no understanding. If you want to do that, go ahead, but I will seriously try to understand whatever I need to do.
Thanks so much to anyone who responds. :)
ORIGINAL SCRIPT
var maxSpeed : float = 1.0;
var minSpeed : float = 0;
var acceleration : float = .02;
var speed = 25;
var jumpSpeed : float = 5;
var gravity : float = 16;
private var moveDirection : Vector3 = Vector3.zero;
var curSpeed : float = 0;
function Update ()
{
// Move it
transform.Translate(transform.forward * curSpeed);
// Accelerate
curSpeed += Input.GetAxis("Vertical") * acceleration;
// Stop it from going too fast
curSpeed = Mathf.Clamp(curSpeed, minSpeed, maxSpeed);
// Jumping/Checking if grounded
var controller : CharacterController = GetComponent(CharacterController);
if (controller.isGrounded) {
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed;
}
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
}
CHARACTER CONTROLLER SCRIPT
var speed : float = 25.0;
var jumpSpeed : float = 10.0;
var gravity : float = 26.0;
private var moveDirection : Vector3 = Vector3.zero;
function Update() {
var controller : CharacterController = GetComponent(CharacterController);
if (controller.isGrounded) {
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed;
}
}
// Destroy and restart level if below Y position -30. (Falling)
if (transform.position.y < -30)
{
Destroy(gameObject);
Application.LoadLevel(0);
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
}
I remember that question! I work in C#, so sorry I can't really help you that much with JS specifics. Other than that, I think you should avoid using CharacterControllers for anything- while they're good for one very specific thing, any other tasks end up failing.
I recommend using raycasts for collision detection, and Translate. This will give you complete control over the player's behaviour, without sacrificing speed or physics. You only really need a very simple physics engine for this- when it's on the ground, keep vertical speed at zero, when it's not on the ground increase verticalspeed by gravity, and use raycasts every frame to deter$$anonymous$$e what would be hit in a given frame's movement.
I have been looking around at raycasts today but don't exactly understand how to use them correctly yet. And yeah, CharacterControllers are very touchy. This small problem I'm having here is overshadowed by a much larger problem with the CC only allowing a capsule collider. I still have to find a way around that. If you think the typical Translate + raycasts is the way to go, then I will certainly look into that. Thanks!
Also, there are only two types of collisions I'll really have in the game.
1) If your speed is over a certain amount, (let's say 25%) you will blow up on impact with a "tile". Of course not if you're on top of them (that's the whole point of Skyroads) but if you go head on on the X or Z axes.
2) If speed is below 25% you gently bump into a tile/block and your speed is set to 0. Simple.
So this should be relatively easy to do. Thanks for the help. I'll look into Raycasts and try to perfect using Translate ins$$anonymous$$d. :)
Raycast is the principal of the blind-man cane. A ray is thrown in the chosen direction at a chosen length. If the ray is cut, it indicates something on the way. Have a look there for Raycast.Collision :http://unity3d.com/support/documentation/ScriptReference/Collider.Raycast.html
Your answer
Follow this Question
Related Questions
Any way to disable SimpleMove's sliding? 1 Answer
CharacterController - moving while jumping (movement vector values reset?) 1 Answer
move enemy to old position of player 2 Answers
Moving objects diagonally with the CharacterController.Move command 1 Answer
Two near-identical scripts cause a cat to jump in different ways - why? 2 Answers