Unity C# instantiating "position + x, y, z"? - c#

So I have a character that uses a weapon and I currently have it set to spawn on my character's position. I want that position to be my character plus a little bit to the right (x-axis). I have no clue how to do this and couldn't find the answer on google. I am a beginner so please be specific. Here is my code:
public float speed = 2f;
Animator anim;
private Rigidbody2D rb2d;
public float jumpHeight = 20f;
public GameObject weapon;
private Vector2 playerPos;
public GameObject player;
private void Start()
{
anim = GetComponent<Animator>();
rb2d = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
playerPos = player.transform.position;
if (Input.GetKey(KeyCode.D))
{
anim.SetInteger("State", 1);
transform.Translate(new Vector2(1f * speed * Time.deltaTime, 0f));
}
if (Input.GetKeyUp(KeyCode.D))
{
anim.SetInteger("State", 3);
}
if (Input.GetKey(KeyCode.A))
{
anim.SetInteger("State", 2);
transform.Translate(new Vector2(-1f * speed * Time.deltaTime, 0f));
}
if (Input.GetKeyUp(KeyCode.A))
{
anim.SetInteger("State", 4);
}
if (Input.GetKey(KeyCode.P))
{
rb2d.AddForce(Vector2.up * jumpHeight);
}
if (Input.GetKeyDown(KeyCode.O))
{
Instantiate(weapon, playerPos, Quaternion.Euler(0, 0, -40));
}
}

In Unity, Transform.position is a Vector3. You can add two Vector3 together with the + operator:
Vector3 result = myVectorA + myVectorB
// or
Vector3 result = new Vector3(5,6,7) + new Vector3(10,0,0) // result is (15,6,7)
To add to the playerPos's x value - you need to add a full Vector3 that just has the necessary translation as it's x value.
playerPos + new Vector3(100, 0, 0)
Details on Unity's vector arithmetic can be found here: https://docs.unity3d.com/Manual/UnderstandingVectorArithmetic.html
And this answer on Unity explains why you cannot also just assign directly into playerPos.x: http://answers.unity3d.com/questions/600421/how-to-change-xyz-values-in-a-vector3-properly-in.html

Related

Unity: How to move object in direction camera is facing

I'm using Unity and trying to move my player object in a direction relative to where the camera is facing. The camera is currently able to rotate/orbit around the player object by using the mouse, however, it only moves in directions relative to the world, not the camera. In essence, I'm trying to replicate what the game Absolver does. There's a good clip in this youtube video at around 4:30 showing the camera/player movement: https://www.youtube.com/watch?v=_lBqCTeJwYw&t=1199s.
I've looked at youtube videos, unity answers and scripting manuals dealing with joysticks, quaternions, and Euler values, but I just can't seem to find a solution that fits my particular problem. Any help would be absolutely great. Thanks in advance!
Camera Rotation Code:
using UnityEngine;
public class FollowPlayer : MonoBehaviour
{
private const float Y_ANGLE_MIN = 0f;
private const float Y_ANGLE_MAX = 85f;
public Transform lookAt;
public Transform camTransform;
private Camera cam;
private float distance = 10f;
private float currentX = 0f;
private float currentY = 0f;
private float sensitivityX = 5f;
private float sensitivityY = 5f;
private void Start()
{
camTransform = transform;
cam = Camera.main;
}
private void Update()
{
currentX += Input.GetAxis("Mouse X") * sensitivityX;
currentY -= Input.GetAxis("Mouse Y") * sensitivityY;
currentY = Mathf.Clamp(currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
}
private void LateUpdate()
{
Vector3 dir = new Vector3(0, 0, -distance);
Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
camTransform.position = lookAt.position + rotation * dir;
camTransform.LookAt(lookAt.position);
}
}
Player Movement Code:
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public Rigidbody rb;
public Camera cam;
public float movementForce = 500f;
// Update is called once per frame
void FixedUpdate()
{
if (Input.GetKey("w"))
{
rb.AddForce(0, 0, movementForce * Time.deltaTime, ForceMode.VelocityChange);
}
if (Input.GetKey("a"))
{
rb.AddForce(-movementForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if (Input.GetKey("s"))
{
rb.AddForce(0, 0, -movementForce * Time.deltaTime, ForceMode.VelocityChange);
}
if (Input.GetKey("d"))
{
rb.AddForce(movementForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if (rb.position.y < -1f)
{
FindObjectOfType<GameManager>().EndGame();
}
}
}
You want to use the transform.forward property of your camera.
Something like this:
rb.AddForce(cam.transform.forward * movementForce * Time.deltaTime, ForceMode.VelocityChange);
You also have at your disposal:
transform.left
transform.right
There is an example of exactly this on the AddForce docs.

Rotating Rigidbody controller

There is my script Rigidbody controller -
public float Speed = 5f;
public float JumpHeight = 2f;
public float GroundDistance = 0.2f;
public float DashDistance = 5f;
public LayerMask Ground;
private Rigidbody _body;
private Vector3 _inputs = Vector3.zero;
private bool _isGrounded = true;
private Transform _groundChecker;
void Start()
{
_body = GetComponent<Rigidbody>();
_groundChecker = transform.GetChild(0);
}
void Update()
{
_isGrounded = Physics.CheckSphere(_groundChecker.position, GroundDistance, Ground, QueryTriggerInteraction.Ignore);
_inputs = Vector3.zero;
_inputs.x = Input.GetAxis("Horizontal");
_inputs.z = Input.GetAxis("Vertical");
if (_inputs != Vector3.zero)
transform.forward = _inputs;
if (Input.GetButtonDown("Jump") && _isGrounded)
{
_body.AddForce(Vector3.up * Mathf.Sqrt(JumpHeight * -2f * Physics.gravity.y), ForceMode.VelocityChange);
}
if (Input.GetButtonDown("Sprint"))
{
Vector3 dashVelocity = Vector3.Scale(transform.forward, DashDistance * new Vector3((Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime), 0, (Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime)));
_body.AddForce(dashVelocity, ForceMode.VelocityChange);
}
}
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
}
What the best way to make a turn on y in the direction of the camera ? That is,the player turns to the side where the mouse is turned? Is it in fixedUpdate or update?
This is the camera script:
public float Smoothness = 0.3F;
public Vector2 Sensitivity = new Vector2(4, 4);
public Vector2 LimitX = new Vector2(-70, 80);
private Vector2 NewCoord;
public Vector2 CurrentCoord;
private Vector2 vel;
public GameManager GameMangerS;
public Transform Target;
public float TransformSpeed;
public Animator CameraAnimator;
void Update()
{
NewCoord.x = Mathf.Clamp(NewCoord.x, LimitX.x, LimitX.y);
NewCoord.x -= Input.GetAxis("Mouse Y") * Sensitivity.x;
NewCoord.y += Input.GetAxis("Mouse X") * Sensitivity.y;
CurrentCoord.x = Mathf.SmoothDamp(CurrentCoord.x, NewCoord.x, ref vel.x, Smoothness / 2);
CurrentCoord.y = Mathf.SmoothDamp(CurrentCoord.y, NewCoord.y, ref vel.y, Smoothness / 2);
transform.rotation = Quaternion.Euler(CurrentCoord.x, CurrentCoord.y, 0);
}
And added this line to the controller script -
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Euler(0, MainCamera.CurrentCoord.y, 0);
}
When I'm standing the player normally rotates, but when I start to move, all rotations are reset and the player is not moving.
Update
Simple Rotation can be achieved using transform.Rotate().
Example:
this.transform.Rotate(Vector3.up, 30);
This example is gonna rotate the transform by 30° around the Vector that points upwards.
LookAtMouse:
To make your object turn towards the mouse, you need the ScreenToWorldSpace() method from your camera. In order to convert the ScreenCoordinates into your WorldCoordinates.
Example:
Please note:
You have to set the camera instance! If you don't add that, you'll get a NullReferenceException.
This Snippets shall only show the steps needed to achieve the behavior you wish.
You will have to find out yourself how to integrate that lines of code into your code to make it work. Consider what Programmer told you in the comment when integrating that.
Vector3 mousePosition = Input.mousePosition; //get the screenSpaceMousePosition
Vector3 worldPosition = this.camera.ScreenToWorldPoint(mousePosition); //convert it into worldSpacePosition
Vector3 calculatedDirection = worldPosition - transform.position; //calucate the looking direction
calculatedDirection.y = 0;
Quaternion rotation = Quaternion.LookRotation(calculatedDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);

How can i rotate a spaceship back to it's original rotation to face the original position?

The spaceship start moving from point A. The spaceship is facing the moving direction.
Now when i click one on the L key i want that the spaceship will rotate and will face to the original position it was start moving from. But even if the spaceship is now rotated by axis Z or Y or X to rotate it first to the regular rotation values and to face to the start moving position.
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour
{
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private Vector3 originalPosition;
private Quaternion originalRotation;
// Use this for initialization
void Start()
{
originalPosition = transform.position;
originalRotation = transform.rotation;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey("p"))
{
isPKeyDown = Input.GetKey("p");
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
if (Input.GetKey("l"))
{
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0);
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
}
IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while (lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is where i click the L button but i tried some things but can't yet find how to do it.
The main goal is if i click once on L the spaceship should automatic rotate if needed and move back to the original position and then land on ground. L stand for landing that's the main goal.
Add a variable on top -
...
private Vector3 originalPosition;
private Quaternion originalRotation;
private bool landShip = false;
...
And use following code in update function -
if (Input.GetKey("l"))
{
landShip = true;
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
if(landShip){
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0.5f);
}
Once the spaceship lands, set the landShip value back to false.

Camera always behind player in Unity3d

I'm struggling with this for quit some time now. I have GameObject, being a sphere, which is my player on a 3d Terrain. I have a Camera which is always on a fixed distance from the player, follows it where it goes with below script:
public GameObject player;
private Vector3 offset;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
}
void LateUpdate () {
transform.position = player.transform.position + offset;
}
So far so good. However what I actually want is that the camera rotates with the player, so it always looks into the direction where the sphere is moving, but always stays behind the player at the same fixed distance, so that the player is always visible in the camera view.
There are a lot of scripts available, but the problem with the onces I've seen so far is that the camera indeed rotate with the player, but because the player actually is a rolling sphere the camera view is rolling and turning as well.
The best script I found so far is below, but this one has the same problem as the other onces, the camera rolls with the player.
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
//Quaternion ownRotation = Quaternion.RotateTowards;
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
Can anyone help me with this please?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour {
public GameObject player;
public float cameraDistance = 10.0f;
// Use this for initialization
void Start () {
}
void LateUpdate ()
{
transform.position = player.transform.position - player.transform.forward * cameraDistance;
transform.LookAt (player.transform.position);
transform.position = new Vector3 (transform.position.x, transform.position.y + 5, transform.position.z);
}
}
My solution (based on #brennon-provencher answer) with smoothness and auto offset:
public class CameraFollow : MonoBehaviour
{
public GameObject target;
public float speed = 5;
Vector3 offset;
void Start()
{
offset = target.transform.position - transform.position;
}
void LateUpdate()
{
// Look
var newRotation = Quaternion.LookRotation(target.transform.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, speed * Time.deltaTime);
// Move
Vector3 newPosition = target.transform.position - target.transform.forward * offset.z - target.transform.up * offset.y;
transform.position = Vector3.Slerp(transform.position, newPosition, Time.deltaTime * speed);
}
}
You need to move your camera position based on sphere movement direction -
public GameObject player;
private Vector3 offset;
float distance;
Vector3 playerPrevPos, playerMoveDir;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
distance = offset.magnitude;
playerPrevPos = player.transform.position;
}
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
Edit 2: To fix flickering camera, try this -
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.position.y += 5f; // required height
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
}

Make camera follow x-axis only

Trying to make it follow x-axis only. Only follows y when I replace with .y .y
It just doesn't want to work, no matter what I try. (Just started game dev today) I'm pretty noob at coding.
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour
{
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start()
{
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate()
{
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
Vector3 factorTowardsTarget = (targetDirection.normalized * interpVelocity * Time.deltaTime);
targetPos = new Vector3(transform.position.x, transform.position.y + factorTowardsTarget.y, transform.position.z);
transform.position = Vector3.Lerp(transform.position, targetPos + offset, 0.25f);
}
}
}
I don't really know much about what I'm doing either, but I gave it a shot. This is my first post.
From what I understand there's a certain order they have to be in, X then Y then Z. And the Y is what was getting the modifier added to it. I just put the modifier on the X position instead.
I tested it, it seems to work.
I just changed this part:
targetPos = new Vector3(transform.position.x, transform.position.y + factorTowardsTarget.y, transform.position.z);
To this:
targetPos = new Vector3(transform.position.x + factorTowardsTarget.x, transform.position.y, transform.position.z);
Result:
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour
{
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start()
{
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate()
{
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
Vector3 factorTowardsTarget = (targetDirection.normalized * interpVelocity * Time.deltaTime);
targetPos = new Vector3(transform.position.x + factorTowardsTarget.x, transform.position.y, transform.position.z);
transform.position = Vector3.Lerp(transform.position, targetPos + offset, 0.25f);
}
}
}
This code makes the camera follow the object only on the x position
public Camera MyCamera; // The camera you want to follow the GameObject
public GameObject ObjectToFollow; // What you want to follow
private Vector3 CameraPos; // Variable that contains the Cameras x,y,z position
void Start()
{
CameraPos = MyCamera.transform.position; // stores the Camera's position in the variable
}
// Update is called once per frame
void Update () {
CameraPos.x = ObjectToFollow.transform.position.x; // Change The X position on the camera variable to be the same as the ObjectToFollow X position
MyCamera.transform.position = CameraPos; // Moves the Camera to the new position
}

Categories