Unity C# camera movement - c#

I'm currently trying to create a Camera Control for unity (to follow around a prefab and be able to zoom and such ...
I am very new to C#
an issue I am having with this script is that
camera zooming to 0,0,0. (when I need it to stay at it's current Y-axis, I tried changing the void "Move()" but the vector requires 3 m_....'s
I also need to write a piece of code that will allow the player to zoom the camera in and out using the
scroll wheel... (In "Public Void Update()"...
I've been looking through guides and videos and can't find anything to assist me with this..
this is the section of code I require help with :
private void FixedUpdate()
{
Move();
}
private void Move()
{
m_DesiredPosition = m_target.position;
transform.position = Vector3.SmoothDamp(transform.position,
m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
}
public void Update()
{
// Get the scroll value of the mouse scroll wheel
// float scroll = Input.GetAxis("Mouse ScrollWheel");
// Is the scroll value not 0?
// Modify the orthographic size by the scroll value
Camera.main.orthographicSize = 4.8f;
}

For keeping the camera at Y = 0 simply override Y:
m_DesiredPosition = m_Target.position;
m_DesiredPosition.Y = 0;
transform.position = Vector3.SmoothDamp(transform.position,
m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
For zooming the camera you'll want to add/subtract the value to orthographicsize instead of simply setting it:
// Zoom in
Camera.main.orthographicSize -= 4.8f;
// Zoom out
Camera.main.orthographicSize += 4.8f;

Related

Keeping camera & mouse movement speeds the same on Drag in Unity3D

this question is a bit long but please bare with me.
I am working with Unity3D's newer input system, and I've been able to set up camera movement so when the user clicks the middle mouse button, they can drag the camera around along the X- & Y-axis. However, has a very parallax-y feel to it, which I am trying to avoid. From my understanding this is happening because the speed of the mouse movement & the camera movements are not the same (See, visual).
My InputController class:
public class InputController : MonoBehaviour
{
private InputControls inputControls;
[Header("Camera Movement")]
[SerializeField] CameraController cameraController;
private InputAction.CallbackContext context;
void Awake()
{
inputControls = new InputControls();
}
private void Start()
{
inputControls.Mouse.MiddleButton.started += MiddleButton_started;
}
public void MiddleButton_started(InputAction.CallbackContext ctx)
{
context = ctx;
}
private void Update()
{
bool mouseIsDown = context.performed;
if (mouseIsDown)
{
Vector2 delta = inputControls.Mouse.DeltaPosition.ReadValue<Vector2>();
cameraController.Move(delta, false);
}
}
}
My CameraController class:
public class CameraController : MonoBehaviour
{
[SerializeField] Vector2 minPosition;
[SerializeField] Vector2 maxPosition;
[SerializeField] float speed = 3;
[SerializeField] float zPosition = -10f;
private Camera mainCam;
private void Start()
{
mainCam = GetComponent<Camera>();
}
public void Move(Vector2 deltaPosition, bool convertToViewportPoint = true)
{
if (convertToViewportPoint) deltaPosition = mainCam.ScreenToViewportPoint(deltaPosition);
Vector3 moveTo = new Vector3(deltaPosition.x, deltaPosition.y, 0);
Vector3 target = transform.position - moveTo;
float clampedX = Mathf.Clamp(target.x, minPosition.x, maxPosition.x);
float clampedY = Mathf.Clamp(target.y, minPosition.y, maxPosition.y);
transform.position = Vector3.Lerp(transform.position, new Vector3(clampedX, clampedY, -10), speed * Time.deltaTime);
}
}
Now, in this version of the CameraController, the parallax-y feel might be coming from the fact that the Lerp speed is constant, whereas the speed of the mouse movement is not.
However, I've tested it with various magnitudes (ie., the magnitudes of the delta mouse position, the current mouse position, the current mouse position subtracted from the delta mouse position, etc...) with generally the same results -- either the camera moves too fast for the mouse or vice versa.
From my limited but growing understanding of trig, magnitudes represents the speed of a vector but I CANNOT get the speed of the camera movement and the speed of the mouse movement to match up. I would like for this to happen so that when the user clicks a certain point, that point generally stays under the cursor when in movement (See other visual).
Can someone help me understand how I might achieve this?
Thanks kindly.
What I did to solve this, in case anyone comes across this, is get the position of the cursor when the mouse is first clicked. We can call that dragOrigin. Then we can get the change in position as the mouse moves (polling the input through Unity's input system can be done through an Update function). Then we subtract the new mouse position from dragOrigin. Once we have that difference -- lets call it deltaPosition -- we just add it to the camera's current position.
To ensure that the speed matches that of the mouse, run the deltaPosition and the currentMousePosition through SmoothDamp to get the velocity of the change. Its magnitude will be the speed you want the camera to move.
So for example:
// Call this when the user first clicks the mouse.
// Lets assume this is part of a class that controls the camera.
public void SetDragOrigin(Vector2 mousePosition)
{
// could probably cache Camera.main for efficiency
dragOrigin = Camera.main.ScreenToWorldPoint(mousePosition);
}
// This is called in an update function of another class that deals with input.
// (Or perhaps you can simply pass the input controls to the class controlling the camera, but that's not the case here).
public void Move(Vector2 newMousePosition)
{
mousePosition = mainCam.ScreenToWorldPoint(mousePosition);
Vector2 deltaPosition = dragOrigin - mousePosition;
Vector3.SmoothDamp(deltaPosition, mousePosition, ref dragVelocity, 0.1f, 250f, Time.deltaTime);
cameraPosition += new Vector3(deltaPosition.x, deltaPosition.y, 0) * dragVelocity.magnitude * Time.deltaTime;
// anything else you want to do like clamping camera position
// ....
}
One thing to note here, is that the 5th argument of SmoothDamp is the maxSpeed. I hardcoded it in this example, but you might want to play around with it. When I did not set the maxSpeed, there was some wonky things happening to the dragVelocity over time, so it may be better to set the maxSpeed to what suits you best.

My scroll wheel isn't working at all in unity w/ c#?

I'm trying to modify a script that lets the player zoom the camera. Before, scrolling to change the fov worked fine but i wasn't happy with the high fov stretching around the edges so I decided to switch to physical camera movement. For some reason my scroll input doesn't work anymore? This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cameraManager : MonoBehaviour
{
public GameObject cameraAnchor;
public int cameraState;
public Transform playerPos;
public float maxZoomX;
public float maxZoomY;
public float zoomSensitivity;
// Update is called once per frame
void Update()
{
cameraAnchor.transform.position = (playerPos.position + new Vector3(6,10,0)); //camera anchor position relative to player
if (cameraState == 3){
Vector3 zoom = Camera.current.transform.position;
zoom.x += Input.GetAxis("Mouse ScrollWheel") * zoomSensitivity; // changing camera location with scroll wheel
zoom.y += Input.GetAxis("Mouse ScrollWheel") * zoomSensitivity; // changing camera location with scroll wheel
zoom.x = Mathf.Clamp(zoom.x, cameraAnchor.transform.position.x, cameraAnchor.transform.position.x + maxZoomX); // clamping zoom
zoom.y = Mathf.Clamp(zoom.y, cameraAnchor.transform.position.y, cameraAnchor.transform.position.y + maxZoomY); // clamping zoom
print(Input.GetAxis("Mouse ScrollWheel"));//testing scroll input
Camera.current.transform.position = zoom; //setting zoom
}
else{
Camera.current.transform.position = cameraAnchor.transform.position; //reset camera anchor if not in 3rd person
}
}
}
As you can see above, i've tested scrolling with print, which constantly produces a 0, regardless of whether i'm scrolling or not. I've looked at the input settings for the project and everything looks fine there.
Edit: here's a screenshot of my input page
I had this same problem. I loaded up a new project, copied the Mouse ScrollWheel entry from the input settings, and then pasted it into my old project. This resolved the issue. I didn't figure out what caused the issue in the first place.

Make Canvas to follow the camera

I want an UI canvas to follow the camera so it will be in front of the head always and also interactable like VR menu. I'm using the following code to do so.
public class FollowMe : MonoBehaviour
{
public GameObject menuCanvas;
public Camera FirstPersonCamera;
[Range(0, 1)]
public float smoothFactor = 0.5f;
// how far to stay away fromt he center
public float offsetRadius = 0.3f;
public float distanceToHead = 4;
public void Update()
{
// make the UI always face towards the camera
menuCanvas.transform.rotation = FirstPersonCamera.transform.rotation;
var cameraCenter = FirstPersonCamera.transform.position + FirstPersonCamera.transform.forward * distanceToHead;
var currentPos = menuCanvas.transform.position;
// in which direction from the center?
var direction = currentPos - cameraCenter;
// target is in the same direction but offsetRadius
// from the center
var targetPosition = cameraCenter + direction.normalized * offsetRadius;
// finally interpolate towards this position
menuCanvas.transform.position = Vector3.Lerp(currentPos, targetPosition, smoothFactor);
}
}
Unfortunately, the canvas is flickering in front fo the camera and it is not properly positioned. How do I make the menu to follow the camera?|
If there is no reason against it you can use a ScreenSpace - Camera canvas as stated in the docs. Then you can reference your FPS camera as the rendering camera for the canvas.
Easy way to do this is using Screen Space - Camera mode which you can setup from Canvas component and in Render Mode properties.
Second way if you want more control over how your canvas should behave then you can use Canvas Render Mode - "World Space" and then using script you can handle canvas a some gameobject.

Rotation of a Sprite Around Its Pivot

I have a class below that I attach to a object in order to make it rotate around its pivot. I sent the pivot of the sprite via the inspector.
This works exactly how I want it too, BUT the issue I am having is that whenever I touch and drag it, and then touch and drag it again, it snaps to a new position.
What I would like for it to do is, when it is rotated and then rotated again, the sprite stays in its same rotation and not snap to a new position and I would like the angle of the sprite to be reset to 0. The next then is that I want the angle to continually rotate. So if I rotate it in the positive direction, the angle should keep increasing in the positive direction and not change..Such as 0---> 360 ----> 720 -----> etc, etc. And then when the mouse is released, the sprite stays in the same position but the angle is now set back to 0. And then when clicked again to rotate, it rotates from that exact position.
Here is my code thus far which works well for rotating, but I would like to modify it to achieve the above scenario. Any help with this?
public class Steering : MonoBehaviour {
float prevAngle,wheelAngle,wheelNewAngle = 0;
public SpriteRenderer sprite;
void Start () {
}
void Update () {
}
public float GetAngle(){
return wheelAngle;
}
void OnMouseDrag(){
Vector3 mouse_pos = Input.mousePosition;
Vector3 player_pos = Camera.main.WorldToScreenPoint(this.transform.position);
mouse_pos.x = mouse_pos.x - player_pos.x;
mouse_pos.y = mouse_pos.y - player_pos.y;
wheelNewAngle = Mathf.Atan2 (mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg;
if (Input.mousePosition.x > sprite.bounds.center.x) {
wheelAngle += wheelNewAngle - prevAngle;
} else {
wheelAngle -= wheelNewAngle - prevAngle;
}
this.transform.rotation = Quaternion.Euler (new Vector3(0, 0, wheelAngle));
Debug.Log (wheelAngle);
prevAngle = wheelNewAngle;
}
void OnMouseUp(){
prevAngle = wheelNewAngle;
wheelAngle = 0;
}
}
By angle of the sprite, do you mean the rotation? I'm not sure how the position is changing if there's nothing in your code doing that. Does it always move to the same position? I'm having a little trouble visualizing how your system is supposed to look but I hope this helps.
It looks like you might want to store the previous mouse position so you can get the relative amount to rotate each frame.
At the top:
Vector3 prevMousePos = Vector3.zero;
This method will help get the position when the player pressed:
void OnMouseDown(){
prevMousePos = Input.mousePosition;
}
Then in OnMouseDrag() get the difference between the two mouse positions to get the relative position (if you moved the mouse left, right, up, or down since pressing):
Vector3 mouseDiff = Input.mousePosition - prevMousePos;
With this it will use the relative mouse position after pressing instead of the current one, which should smooth things out.

Mouse event wont update camera rotation in winforms

My app has a custom panel used to display the XNA screen within a WinForm. I've currently displayed a test model with no problem and now working on camera movement. My camera is a Free Camera (not bound to look at any specific target), but I've been having trouble getting the mouse to update the yaw and pitch of the camera on its own axis. I thought maybe something was wrong with my update method, but that wasn't the case, because the camera updates moving forward and backwards using KeyboardState. But I have no idea as to why the MouseState isn't working.
FreeCamera.cs
using XNAButtonState = Microsoft.Xna.Framework.Input.ButtonState;
....
MouseState pastMouseState;
private float rotationSpeed_ = 1f / 60f;
private float yaw_, pitch_;
...
private void updateMatrix()
{
Matrix rotationMatrix = Matrix.CreateRotationX(pitch_) *
Matrix.CreateRotationY(yaw_);
Vector3 forward = new Vector3(0, 0, 1);
forward = Vector3.Transform(forward, rotationMatrix);
viewMatrix_ = Matrix.CreateLookAt(Position, Position + forward, Up);
projectionMatrix_ = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4, 16.0f / 9.0f, 0.1f, 100000.0f);
}
private void cameraInput()
{
KeyboardState keyboardState = Keyboard.GetState(); <-- updates
currentMouseState = Mouse.GetState(); <-- not updating
if (currentMouse.LeftButton == XNAButtonState.Pressed)
pitch_ -= rotationSpeed_;
if (keyboardState.IsKeyDown(Keys.W))
move(1);
if (keyboardState.IsKeyDown(Keys.S))
move(-1);
pastMouseState = currentMouseState;
}
public void update()
{
cameraInput();
updateMatrix();
In order to use XNA's mouse API (rather than WinForm events) you must set Mouse.WindowHandle appropriately (MSDN).
If you are using the official samples, then putting this in your MainForm's constructor will do the trick:
Mouse.WindowHandle = this.Handle;
(Of course using Microsoft.Xna.Framework.Input;)

Categories

Resources