I have been looking around for ages about how to do a Real-time Strategy camera for Unity in 2D. What I mean is that you should be controlling the camera with W, A, S, D and where ever I look its only 3D. I have been trying to write my own scripts but the camera never works and I am in dire need for help. I have tried so much but as a beginner on Unity, I really need help with this. If you can give me anything about how to get started in this matter I will be so happy.
Do you think I should use the Force method or that I should use another one that unity already has installed? I also tried using vectors but when I looked around everyone was using Vector 3 which only is for 3D unity.
You can attach a single script to your camera.
public float speed =10.0f;
void Update()
{
Vector3 a = transform.position
if(Input.GetKeyDown("W"))
{
a.position.y += speed *Time.deltaTime
}
if(Input.GetKeyDown("S"))
{
a.position.y -= speed *Time.deltaTime
}
transform.position =a;
}
You can adjust the speed to your needs. You can do this for other keys. Note GetKeyDown is called when a key is being held down. Hope this helps.
Make a direction vector with Vector3 direction = new Vector3();
Manipulate the vector in the directions you want, based on the key:
if (Input.GetKey(KeyCode.A))
direction += Vector3.left;
Adding the "built-in" Vector3.left will point the direction of the vector to the left, and you can add the other keys on top of that to get a final direction.
Then you can use transform.Translate() to move the gameObject (in this case you attached it to your camera) by passing the direction you calculated based on the keys being pressed as a parameter. Then multiply to get direction * speed * Time.deltaTime;
Related
Hey stackoverflow Community,
First of all:
I'm still very new about programming with C# and Unity.
My question:
I'm working on an idea for a Movement of a Cube.
It is planned that the cube will move forward by pressing a key (W-Key). But it shouldn't just move forward. It should jump forward to the next point. So always plus 1 of its axis into which it should go. Accordingly, it is only intended to go forward, right, down, left. He won't be able to jump over behind. You should also see that the cube jumps in the respective direction, so it should not teleport itself. :D
Does anyone have an idea how I can realize this movement?
I am very much looking forward to your ideas.
(Sorry if my English is not so good, my English not the best. ^^)
best regards
xKarToSx
So, in order to understand movement, it's best to first understand Vectors in Unity. Since you want to be moving the cube in the forward direction, I'm going to assume this is a 3D game, in which case you want to use a Vector3.
A Vector3 has three components: X, Y, and Z. Each component is tied to an axis. In simple terms, X is tied to left and right, Y is tied to up and down, and Z is tied to forward and back. So, Vector3 position = new Vector3(0, 1, 2); will be a vector that is 1 unit above and 2 units in front of the starting position.
Assuming you've attached this script to the cube you want to move, you can track its position with transform.position. So, if you want to move the cube one unit forward, your code would look something like this:
if(Input.GetKeyDown(KeyCode.W)) // This code will activate once the user presses W.
{
transform.position += new Vector3(0, 0, 1);
}
That will move the cube one unit forward in the Z direction. However, you don't want it to teleport, you want to see it move, correct? In that case, you want to check out Unity's Vector3.Lerp function. Basically, you would use it to smoothly transition an object between two defined positions. You'll need to implement a timer and a for loop in order to make this work correctly.
So, to summarize, for moving one unit forward in the Z direction, your code would look something like this:
if(Input.GetKeyDown(KeyCode.Z))
{
float startTime = Time.time; //Time.time is the current in-game time when this line is called. You'll want to save this to a variable
float speed = 1.0f; //The speed if something you'll want to define. The higher the speed, the faster the cube will move.
Vector3 startPosition = transform.position; //Save the starting position to a different variable so you can reference it later
Vector3 endPosition = startPosition + Vector3.forward; //Vector3.Forward is equivalent to saying (0, 0, 1);
float length = Vector3.Distance(startPosition, endPosition); //You'll need to know the total distance that the cube will move.
while(transform.position != endPosition) //This loop while keep running until the cube reaches its endpoint
{
float distCovered = (Time.time - startTime) * speed; //subtracting the current time from your start time and multiplying by speed will tell us how far the cube's moved
float fraction = distCovered / length; //This will tell us how far along the cube is in relation to the start and end points.
transform.position = Vector3.Lerp(startPosition, endPosition, fraction); //This line will smoothly transition between the start and end points
}
}
I hope this helps you. This is my first time answering a question so sorry if I got some things wrong/it's not the most optimized. Good Luck!
I'm trying to rotate my camera around a character, with a certain direction it needs to face. For example, I want my camera to rotate around my character, and stop the rotation when it faces another objects forward axis.
So I figured I needed a combination between RotateAround() and LookRotation().
RotateAround() to rotate the camera around the character, and LookRotation() to make the camera face that object aswell.
The problem is: I don't want my camera to move or rotate away from my character.
I tried a couple of things, the most thought out being this:
private void RotateCamera()
{
Quaternion currentCameraRotation = _camera.transform.rotation;
Quaternion futureCameraRotation = Quaternion.LookRotation(_hitObstacleStartingPoint.transform.forward);
float rotationAngle;
Vector3 rotationAxis;
Quaternion.FromToRotation(currentCameraRotation.eulerAngles, futureCameraRotation.eulerAngles).ToAngleAxis(out rotationAngle, out rotationAxis);
_camera.transform.RotateAround(_character.transform.position, _camera.transform.up, rotationAngle);
}
But that ended up in my camera rotating all over the place..
Thanks in advance!
EDIT: I'm sorry for my terrible explanation.
Here's a little drawing.
If you calculate the distance between the current rotation angle, and the target rotation angle, and you can rotate around the pivot over time.
See below:
private void RotateCamera()
{
Quaternion currentCameraRotation = _camera.transform.rotation;
Quaternion futureCameraRotation = Quaternion.LookRotation(obstacleObject.transform.forward, obstacleObject.transform.up);
float angleDelta = Quaternion.Angle(currentCameraRotation, futureCameraRotation);
_camera.transform.RotateAround(this._character.transform.position, _camera.transform.up, angleDelta * rotationSpeed * Time.deltaTime);
}
To help visualize what's going on:
void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawLine(_camera.transform.position, _camera.transform.forward * 20 + _camera.transform.position);
Gizmos.color = Color.red;
Gizmos.DrawLine(obstacleObject.transform.position, obstacleObject.transform.forward * 20 + obstacleObject.transform.position);
}
This doesn't work if your obstacle is rotated around x,z; it's always assuming a identity forward vector.
I ended up using fixed camera points in my scene. It avoids the problem, so I don't consider this one solved, but I have a deadline on this project and I can't afford to spend too much time on this problem anymore. Thanks to those of you who have helped me.
In my 2D side-scrolling game I move my character using the built-in physics engine by manipulating the rigidbody.velocity.
I would like to add some sort of dodge (roll) ability, where the character moves 3 units in its direction.
Here is the code I used:
void FixedUpdate() {
if (Input.GetKeyDown(KeyCode.A) ) {
Vector2 pos = rb.position;
pos.x -= 5;
rb.MovePosition (pos);
}
}
This method works but the character kind of jumps to the position rather than moving to it (Lerping?) and also doesn't detect collisions despite the body type being dynamic.
Then I tried this:
if (Input.GetKeyDown(KeyCode.A)) {
rb.AddForce(new Vector2(-50, 0));
}
I found the AddForce way isn't accurate at all.
Is there a proper way of doing this?
Maybe you could change the Transform.pos inside Vector2.Lerp to make it look smooth? (Sorry, not enough experience with 2D in unity.)
Just increase rigibody.velocity for a set time. Your chararter object could then play a fitting aniamtion. If The player should not be able to cancle midrole jsut block the controls for that time.
I'm working on converting a simple project of mine into a VR game. Currently, it's just a motorcycle that will zoom forward, and the player can use A or D (or left and right) to steer the cycle.
Here's my code so far:
void Start () {
cycleSphere = GetComponent<Rigidbody>();
}
void Update () {
inputX = Input.GetAxis("Horizontal");
}
void FixedUpdate () {
if (currentSpeed < maxSpeed)
currentSpeed += acceleration;
if (currentSpeed > 0)
cycleSphere.transform.Rotate (0, inputX, 0);
cycleSphere.velocity += transform.forward * currentSpeed;
}
I've imported GoogleVR SDK v1.70.0 and added the prefab, which allows me to view the game on my phone in VR and even look around without touching the code.
I want to make it so that if the player tilts his head left or right, the cycle will turn in the respective direction. How do I do that? Do I use Input.Gyro?
I've done something similar to this before, I made Pacman in Virtual Reality where tilting your head would steer the player (As in, tilting your head to the left so that your ear touches your shoulder, would steer the player, and vice versa).
I did it using Input.acceleration
For example, you can do something as simple as this:
void Update()
{
transform.Rotate(0f, Input.acceleration.x * acceleratorSensitivity, 0f);
}
Basically, you take the X rotation of your device (which would be your head tilting), apply your sensitivity (higher sensitivity means faster turning), and rotate your transform accordingly! :-)
I also think this approach is better than using the gyroscope as not all devices contain a gyroscope, but the majority of devices contain accelerometers (which at its basic level, rotates the screen).
You can use the main camera's transform.eulerAngles like so:
private float angle;
Update() {
angle = transform.eulerAngles.z;
}
This gives you the number of degrees of tilt, where a low value means tilting to the left, and a high (~360) value means tilting to the right.
In my testing just now it seems to give values of up to +-10 depending on where you look, even without any rotation.
I have found a solution for this if I were to be using translation as a means of movement:
http://answers.unity3d.com/questions/1035804/how-do-you-make-an-omnidirectional-2d-character-co.html
however I cannot find a solution for how to do this with my movement being physics based.
I have in my chracters controller the ability to rotate the camera around the z axis:
public Transform target;
private float cameraRot = 3;
if (Input.GetKey("q"))
{
target.transform.Rotate(0, 0, cameraRot);
}
I then have a script on all sprites in the world I am creating that rotates to always face the camera:
public Transform target;
void Start () {
target = GameObject.Find("MainCamera").GetComponent<Transform>();
}
void Update () {
if (target != null)
this.transform.rotation = Camera.main.transform.rotation;
}
That all works fine. However when I have rotated the camera, and therefore the sprites. The rigidbody movements become all skewed as they are rotating in the "global" space and not the "local".
I have tried placing the facecamera script on the child objects only to leave the rigidbody alone but this has no effect.
I hope I made this clear enough and that someone can help.
thank you very much for your time, if I find a solution I will mark the answer as correct and if I fix this myself before an answer I will update with how I fixed it.
The solution was to use:
Rigidbody.AddRelativeForce(Vector2.down * speed);
in lieu of:
Rigidbody.AddForce(Vector2.down * speed);
that adds the force in the local axis not the global.
documentation is here:
https://docs.unity3d.com/ScriptReference/Rigidbody.AddRelativeForce.html