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
Related
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;
I want a sprite to always face the camera, except in the Z-Axis. My sprites keep tipping left or right when I move the camera, and I can't have that.
I have been googling this for hours. I've tried transform.LookAt or Quaternion.LookRotation and manually setting the z to 0, but for whatever reason the z keeps adjusting. I've seen and tried so many solutions that feel like they should work but just don't. If it matters, my sprite is a child of another object, but trying localRotation doesn't work either. Freezing rigidbody constraints also has no effect.
The most accurate I can get it is this:
public class Billboard : MonoBehaviour
{
GameObject cam;
float minDist;
// Start is called before the first frame update
void Start()
{
cam = GameObject.Find("Main Camera");
}
// Update is called once per frame
void LateUpdate()
{
//Scale
minDist = cam.GetComponent<CameraOrbit>().distanceMin;
transform.localScale = new Vector3(1f, 1f, 1f) * (cam.GetComponent<CameraOrbit>().distance - minDist) * 1.01f / 3;
//Direction
transform.LookAt(cam.transform.position);
Vector3 rot = transform.rotation.eulerAngles;
transform.rotation = Quaternion.Euler(rot.x, rot.y, 0);
}
}
With this I can get the sprite to face the camera, but the z axis refuses to stay at zero.
Special thanks to StarManta for answering this question on the Unity Forums.
"OK, I think I see what's happening. Them looking like they're rotated is, I think, an illusion; I think they really are accurately pointing at the camera and right-side-up. But, you're treating the camera as if it has a round/fisheye projection, when it really has a rectilinear projection. Usually this doesn't matter but in this case it does. It's hard to explain exactly how this affects this, but the upshot is that, when things that are on either side of the center of the screen are set to "look towards" the camera, they actually appear to be rotated around their Y axes.
The solution to this is actually annoyingly simple: don't set the rotation to look at the camera, set it to be the same as the camera."
transform.rotation = cam.transform.rotation;
Have you tried rotation constraints?
https://docs.unity3d.com/Manual/class-RotationConstraint.html
I had a similar problem, where I wanted some 3d text to always look up, but rotated to the camera.
What worked for me was setting the undesired euler components to zero after applying the lookat rotation.
In your case, it would be something like this.
transform.LookAt(cam.transform.position);
var rot = transform.rotation.eulerAngles;
transform.rotation = Quaternion.Euler(rot.x, rot.y, 0);
In case you need another z value, just replace the 0.
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.