I had this unity player embedded in android studio activity.
It is a 3d model with animation, which I would like viewer to be able to zoom and view in different angle.
Script are from this link
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MobilemaxCamera : MonoBehaviour {
public Transform target;
public Vector3 targetOffset;
public float distance = 5.0f;
public float maxDistance = 20;
public float minDistance = .6f;
public float xSpeed = 5.0f;
public float ySpeed = 5.0f;
public int yMinLimit = -80;
public int yMaxLimit = 80;
public float zoomRate = 10.0f;
public float panSpeed = 0.3f;
public float zoomDampening = 5.0f;
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
private Vector3 FirstPosition;
private Vector3 SecondPosition;
private Vector3 delta;
private Vector3 lastOffset;
private Vector3 lastOffsettemp;
//private Vector3 CameraPosition;
//private Vector3 Targetposition;
//private Vector3 MoveDistance;
void Start() { Init(); }
void OnEnable() { Init(); }
public void Init()
{
//If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
if (!target)
{
GameObject go = new GameObject("Cam Target");
go.transform.position = transform.position + (transform.forward * distance);
target = go.transform;
}
distance = Vector3.Distance(transform.position, target.position);
currentDistance = distance;
desiredDistance = distance;
//be sure to grab the current rotations as starting points.
position = transform.position;
rotation = transform.rotation;
currentRotation = transform.rotation;
desiredRotation = transform.rotation;
xDeg = Vector3.Angle(Vector3.right, transform.right);
yDeg = Vector3.Angle(Vector3.up, transform.up);
}
/*
* Camera logic on LateUpdate to only update after all character movement logic has been handled.
*/
void LateUpdate()
{
// If Control and Alt and Middle button? ZOOM!
if (Input.touchCount==2)
{
Touch touchZero = Input.GetTouch (0);
Touch touchOne = Input.GetTouch (1);
Vector2 touchZeroPreviousPosition = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePreviousPosition = touchOne.position - touchOne.deltaPosition;
float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude;
float TouchDeltaMag = (touchZero.position - touchOne.position).magnitude;
float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag;
desiredDistance += deltaMagDiff * Time.deltaTime * zoomRate * 0.0025f * Mathf.Abs(desiredDistance);
}
// If middle mouse and left alt are selected? ORBIT
if (Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector2 touchposition = Input.GetTouch(0).deltaPosition;
xDeg += touchposition.x * xSpeed * 0.002f;
yDeg -= touchposition.y * ySpeed * 0.002f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.rotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.rotation = rotation;
if (Input.GetMouseButtonDown (1))
{
FirstPosition = Input.mousePosition;
lastOffset = targetOffset;
}
if (Input.GetMouseButton (1))
{
SecondPosition = Input.mousePosition;
delta = SecondPosition - FirstPosition;
targetOffset = lastOffset + transform.right * delta.x*0.003f + transform.up * delta.y*0.003f;
}
////////Orbit Position
// affect the desired Zoom distance if we roll the scrollwheel
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
position = target.position - (rotation * Vector3.forward * currentDistance );
position = position - targetOffset;
transform.position = position;
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
The zoom in and out work perfectly.
But the problem is, the rotate/pan is totally not working.
Anyone can give some help in this?
For the multi-touch, you have to use this script which I have given below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MultiTouch: MonoBehaviour
{
float initialFingersDistance;
Vector3 initialScale;
float rotationRate = 0.2f;
int direction = 1;
void LateUpdate()
{
if (Input.touches.Length == 1)
{
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Touch touch = Input.touches[0];
Quaternion desiredRotation = transform.rotation;
TouchLogic.Calculate();
if (Mathf.Abs(TouchLogic.turnAngleDelta) > 0)
{ // rotate
Vector3 rotationDeg = transform.eulerAngles;
rotationDeg.z = -TouchLogic.turnAngleDelta;
desiredRotation *= Quaternion.Euler(rotationDeg);
}
// not so sure those will work:
transform.rotation = desiredRotation;
// transform.Rotate(touch.deltaPosition.y * rotationRate, -touch.deltaPosition.x * rotationRate, 0, Space.World);
Vector3 rot = new Vector3(touch.deltaPosition.y * rotationRate, -touch.deltaPosition.x * rotationRate, transform.eulerAngles.z* rotationRate);
// transform.rotation = Quaternion.EulerAngles(rot);
}
}
else if (Input.touches.Length == 2)
{
Touch t1 = Input.touches[0];
Touch t2 = Input.touches[1];
if (t1.phase == TouchPhase.Began || t2.phase == TouchPhase.Began)
{
initialFingersDistance = Vector2.Distance(t1.position, t2.position);
initialScale = gameObject.transform.localScale;
}
else if (t1.phase == TouchPhase.Moved || t2.phase == TouchPhase.Moved)
{
var currentFingersDistance = Vector2.Distance(t1.position, t2.position);
// Debug.Log(currentFingersDistance);
////if (currentFingersDistance != initialFingersDistance)
//{
var scaleFactor = currentFingersDistance / initialFingersDistance;
gameObject.transform.localScale = initialScale * scaleFactor;
//}
float Dx = t1.position.x - transform.position.x;
float Dy = t1.position.y - transform.position.y;
//var cameraTransform = Camera.main.transform.InverseTransformPoint(0, 0, 0);
//transform.position = Camera.main.ScreenToWorldPoint(new Vector3(t2.position.x, t2.position.y, cameraTransform.z -0.5f));
Vector3 pos = t2.position;
//Vector3 pos = t1.position - t2.position;
Vector3 touchedPos = Camera.main.ScreenToWorldPoint(new Vector3(pos.x, pos.y, 10));
transform.position = Vector3.Lerp(transform.position, touchedPos, Time.deltaTime * 4);
// transform.position += touchedPos;
float pinchAmount = 0;
Quaternion desiredRotation = transform.rotation;
TouchLogic.Calculate();
if (Mathf.Abs(TouchLogic.pinchDistanceDelta) > 0)
{ // zoom
pinchAmount = TouchLogic.pinchDistanceDelta;
}
if (Mathf.Abs(TouchLogic.turnAngleDelta) > 0)
{ // rotate
Vector3 rotationDeg = Vector3.zero;
rotationDeg.z = -TouchLogic.turnAngleDelta;
desiredRotation *= Quaternion.Euler(rotationDeg);
}
// not so sure those will work:
transform.rotation = desiredRotation;
transform.position += Vector3.forward * pinchAmount;
}
}
}
}
For your touch control logic, you have to use this second script which I gave below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchLogic: MonoBehaviour
{
const float pinchTurnRatio = Mathf.PI / 2;
const float minTurnAngle = 0;
const float pinchRatio = 1;
const float minPinchDistance = 0;
const float panRatio = 1;
const float minPanDistance = 0;
/// <summary>
/// The delta of the angle between two touch points
/// </summary>
static public float turnAngleDelta;
/// <summary>
/// The angle between two touch points
/// </summary>
static public float turnAngle;
/// <summary>
/// The delta of the distance between two touch points that were distancing from each other
/// </summary>
static public float pinchDistanceDelta;
/// <summary>
/// The distance between two touch points that were distancing from each other
/// </summary>
static public float pinchDistance;
/// <summary>
/// Calculates Pinch and Turn - This should be used inside LateUpdate
/// </summary>
///
static public Touch LastTouch;
static public void Calculate()
{
pinchDistance = pinchDistanceDelta = 0;
turnAngle = turnAngleDelta = 0;
// if two fingers are touching the screen at the same time ...
if (Input.touchCount == 1)
{
Touch touch1 = Input.touches[0];
turnAngle = Angle(touch1.position, LastTouch.position);
float prevTurn = Angle(touch1.position + touch1.deltaPosition,
LastTouch.deltaPosition + LastTouch.position);
turnAngleDelta = Mathf.DeltaAngle(prevTurn, turnAngle);
// ... if it's greater than a minimum threshold, it's a turn!
if (Mathf.Abs(turnAngleDelta) > minTurnAngle)
{
turnAngleDelta *= pinchTurnRatio;
}
else
{
turnAngle = turnAngleDelta = 0;
}
LastTouch =Input.touches[0];
}
else if (Input.touchCount == 2)
{
Touch touch1 = Input.touches[0];
Touch touch2 = Input.touches[1];
// ... if at least one of them moved ...
if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved)
{
// ... check the delta distance between them ...
pinchDistance = Vector2.Distance(touch1.position, touch2.position);
float prevDistance = Vector2.Distance(touch1.position - touch1.deltaPosition,
touch2.position - touch2.deltaPosition);
pinchDistanceDelta = pinchDistance - prevDistance;
// ... if it's greater than a minimum threshold, it's a pinch!
if (Mathf.Abs(pinchDistanceDelta) > minPinchDistance)
{
pinchDistanceDelta *= pinchRatio;
}
else
{
pinchDistance = pinchDistanceDelta = 0;
}
// ... or check the delta angle between them ...
turnAngle = Angle(touch1.position, touch2.position);
float prevTurn = Angle(touch1.position + touch1.deltaPosition,
touch2.position + touch2.deltaPosition);
turnAngleDelta = Mathf.DeltaAngle(prevTurn, turnAngle);
// ... if it's greater than a minimum threshold, it's a turn!
if (Mathf.Abs(turnAngleDelta) > minTurnAngle)
{
turnAngleDelta *= pinchTurnRatio;
}
else
{
turnAngle = turnAngleDelta = 0;
}
}
}
}
static private float Angle(Vector2 pos1, Vector2 pos2)
{
Vector2 from = pos2 - pos1;
Vector2 to = new Vector2(1, 0);
float result = Vector2.Angle(from, to);
Vector3 cross = Vector3.Cross(from, to);
if (cross.z > 0)
{
result = 360f - result;
}
return result;
}
}
Both scripts are used in a single project. using these scripts you can easily rotate your 3d object.
Note: Please attach this both script in a single 3d object, so you can use this script easily.
Related
I wanted to add Guns with recoil to my 3d fps game. It worked but for some reason all the time when i look completely downwards i walk backwards or frontwards. This only happens when the gun is active.
The Gun Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunScript : MonoBehaviour
{
[SerializeField] float Recoil = 500f;
[SerializeField] float TimeTillNextShoot;
[SerializeField] float Range = 100f;
[SerializeField] Transform GunTipposition;
[SerializeField] float recoilRadius = 100f;
public Camera PlayerCamera;
public Rigidbody rbPlayer;
private void Update()
{
Shoot();
}
public void Shoot()
{
if (Input.GetButtonDown("Fire1"))
{
RaycastHit hit;
if(Physics.Raycast(PlayerCamera.transform.position, PlayerCamera.transform.forward, out hit, Range))
{
Debug.Log(hit.transform.name);
Enemy Enemytarget = hit.transform.GetComponent<Enemy>();
if(Enemytarget != null)
{
Enemytarget.TakeDamage(true);
}
}
if (gameObject.CompareTag("ShotGun"))
{
Transform RecoilPosition = GunTipposition.transform;
rbPlayer.AddExplosionForce(Recoil, RecoilPosition.position, recoilRadius);
}
}
}
}
The player Movement:
// Some stupid rigidbody based movement by Dani
using System;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Assignables")]
[Tooltip("this is a reference to the MainCamera object, not the parent of it.")]
public Transform playerCam;
[Tooltip("reference to orientation object, needed for moving forward and not up or something.")]
public Transform orientation;
[Tooltip("LayerMask for ground layer, important because otherwise the collision detection wont know what ground is")]
public LayerMask whatIsGround;
private Rigidbody rb;
[Header("Rotation and look")]
private float xRotation;
[Tooltip("mouse/look sensitivity")]
public float sensitivity = 50f;
private float sensMultiplier = 1.5f;
[Header("Movement")]
[Tooltip("additive force amount. every physics update that forward is pressed, this force (multiplied by 1/tickrate) will be added to the player.")]
public float moveSpeed = 4500;
[Tooltip("maximum local velocity before input is cancelled")]
public float maxSpeed = 20;
[Tooltip("normal countermovement when not crouching.")]
public float counterMovement = 0.175f;
private float threshold = 0.01f;
[Tooltip("the maximum angle the ground can have relative to the players up direction.")]
public float maxSlopeAngle = 35f;
private Vector3 crouchScale = new Vector3(1, 0.5f, 1);
private Vector3 playerScale;
[Tooltip("forward force for when a crouch is started.")]
public float slideForce = 400;
[Tooltip("countermovement when sliding. this doesnt work the same way as normal countermovement.")]
public float slideCounterMovement = 0.2f;
private bool readyToJump = true;
private float jumpCooldown = 0.25f;
[Tooltip("this determines the jump force but is also applied when jumping off of walls, if you decrease it, you may end up being able to walljump and then get back onto the wall leading to infinite height.")]
public float jumpForce = 550f;
float x, y;
bool jumping;
private Vector3 normalVector = Vector3.up;
[Header("Wallrunning")]
private float actualWallRotation;
private float wallRotationVel;
private Vector3 wallNormalVector;
[Tooltip("when wallrunning, an upwards force is constantly applied to negate gravity by about half (at default), increasing this value will lead to more upwards force and decreasing will lead to less upwards force.")]
public float wallRunGravity = 1;
[Tooltip("when a wallrun is started, an upwards force is applied, this describes that force.")]
public float initialForce = 20f;
[Tooltip("float to choose how much force is applied outwards when ending a wallrun. this should always be greater than Jump Force")]
public float escapeForce = 600f;
private float wallRunRotation;
[Tooltip("how much you want to rotate the camera sideways while wallrunning")]
public float wallRunRotateAmount = 10f;
[Tooltip("a bool to check if the player is wallrunning because thats kinda necessary.")]
public bool isWallRunning;
[Tooltip("a bool to determine whether or not to actually allow wallrunning.")]
public bool useWallrunning = true;
[Header("Collisions")]
[Tooltip("a bool to check if the player is on the ground.")]
public bool grounded;
[Tooltip("a bool to check if the player is currently crouching.")]
public bool crouching;
private bool surfing;
private bool cancellingGrounded;
private bool cancellingSurf;
private bool cancellingWall;
private bool onWall;
private bool cancelling;
public static PlayerMovement Instance { get; private set; }
void Awake()
{
Instance = this;
rb = GetComponent<Rigidbody>();
//Create a physic material with no friction to allow for wallrunning and smooth movement not being dependant
//and smooth movement not being dependant on the in-built unity physics engine, apart from collisions.
PhysicMaterial mat = new PhysicMaterial("tempMat");
mat.bounceCombine = PhysicMaterialCombine.Average;
mat.bounciness = 0;
mat.frictionCombine = PhysicMaterialCombine.Minimum;
mat.staticFriction = 0;
mat.dynamicFriction = 0;
gameObject.GetComponent<Collider>().material = mat;
}
void Start()
{
playerScale = transform.localScale;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
readyToJump = true;
wallNormalVector = Vector3.up;
}
private void FixedUpdate()
{
Movement();
}
private void Update()
{
MyInput();
Look();
}
private void LateUpdate()
{
//call the wallrunning Function
WallRunning();
WallRunRotate();
}
private void WallRunRotate()
{
FindWallRunRotation();
float num = 12f;
actualWallRotation = Mathf.SmoothDamp(actualWallRotation, wallRunRotation, ref wallRotationVel, num * Time.deltaTime);
playerCam.localRotation = Quaternion.Euler(playerCam.rotation.eulerAngles.x, playerCam.rotation.eulerAngles.y, actualWallRotation);
}
/// <summary>
/// Find user input. Should put this in its own class but im lazy
/// </summary>
private void MyInput()
{
x = Input.GetAxisRaw("Horizontal");
y = Input.GetAxisRaw("Vertical");
jumping = Input.GetButton("Jump");
crouching = Input.GetKey(KeyCode.LeftControl);
//Crouching
if (Input.GetKeyDown(KeyCode.LeftControl))
StartCrouch();
if (Input.GetKeyUp(KeyCode.LeftControl))
StopCrouch();
}
private void StartCrouch()
{
transform.localScale = crouchScale;
transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
if (rb.velocity.magnitude > 0.2f && grounded)
{
if (grounded)
{
rb.AddForce(orientation.transform.forward * slideForce);
}
}
}
private void StopCrouch()
{
transform.localScale = playerScale;
transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
}
private void Movement()
{
//Extra gravity
rb.AddForce(Vector3.down * Time.deltaTime * 10);
//Find actual velocity relative to where player is looking
Vector2 mag = FindVelRelativeToLook();
float xMag = mag.x, yMag = mag.y;
//Counteract sliding and sloppy movement
CounterMovement(x, y, mag);
//If holding jump && ready to jump, then jump
if (readyToJump && jumping) Jump();
//Set max speed
float maxSpeed = this.maxSpeed;
//If sliding down a ramp, add force down so player stays grounded and also builds speed
if (crouching && grounded && readyToJump)
{
rb.AddForce(Vector3.down * Time.deltaTime * 3000);
return;
}
//If speed is larger than maxspeed, cancel out the input so you don't go over max speed
if (x > 0 && xMag > maxSpeed) x = 0;
if (x < 0 && xMag < -maxSpeed) x = 0;
if (y > 0 && yMag > maxSpeed) y = 0;
if (y < 0 && yMag < -maxSpeed) y = 0;
//Some multipliers
float multiplier = 1f, multiplierV = 1f;
// Movement in air
if (!grounded)
{
multiplier = 0.5f;
multiplierV = 0.5f;
}
// Movement while sliding
if (grounded && crouching) multiplierV = 0f;
//Apply forces to move player
rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * multiplier * multiplierV);
rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * multiplier);
}
private void Jump()
{
if ((grounded || isWallRunning || surfing) && readyToJump)
{
MonoBehaviour.print("jumping");
Vector3 velocity = rb.velocity;
readyToJump = false;
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(normalVector * jumpForce * 0.5f);
if (rb.velocity.y < 0.5f)
{
rb.velocity = new Vector3(velocity.x, 0f, velocity.z);
}
else if (rb.velocity.y > 0f)
{
rb.velocity = new Vector3(velocity.x, velocity.y / 2f, velocity.z);
}
if (isWallRunning)
{
rb.AddForce(wallNormalVector * jumpForce * 3f);
}
Invoke("ResetJump", jumpCooldown);
if (isWallRunning)
{
isWallRunning = false;
}
}
}
private void ResetJump()
{
readyToJump = true;
}
private float desiredX;
private void Look()
{
float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
//Find current look rotation
Vector3 rot = playerCam.transform.localRotation.eulerAngles;
desiredX = rot.y + mouseX;
//Rotate, and also make sure we dont over- or under-rotate.
xRotation -= mouseY;
float clamp = 89.5f;
xRotation = Mathf.Clamp(xRotation, -clamp, clamp);
//Perform the rotations
playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, 0);
orientation.transform.localRotation = Quaternion.Euler(0, desiredX, 0);
}
private void CounterMovement(float x, float y, Vector2 mag)
{
if (!grounded || jumping) return;
//Slow down sliding
if (crouching)
{
rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideCounterMovement);
return;
}
//Counter movement
if (Math.Abs(mag.x) > threshold && Math.Abs(x) < 0.05f || (mag.x < -threshold && x > 0) || (mag.x > threshold && x < 0))
{
rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * -mag.x * counterMovement);
}
if (Math.Abs(mag.y) > threshold && Math.Abs(y) < 0.05f || (mag.y < -threshold && y > 0) || (mag.y > threshold && y < 0))
{
rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * -mag.y * counterMovement);
}
//Limit diagonal running. This will also cause a full stop if sliding fast and un-crouching, so not optimal.
if (Mathf.Sqrt((Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2))) > maxSpeed)
{
float fallspeed = rb.velocity.y;
Vector3 n = rb.velocity.normalized * maxSpeed;
rb.velocity = new Vector3(n.x, fallspeed, n.z);
}
}
/// <summary>
/// Find the velocity relative to where the player is looking
/// Useful for vectors calculations regarding movement and limiting movement
/// </summary>
/// <returns></returns>
public Vector2 FindVelRelativeToLook()
{
float lookAngle = orientation.transform.eulerAngles.y;
float moveAngle = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * Mathf.Rad2Deg;
float u = Mathf.DeltaAngle(lookAngle, moveAngle);
float v = 90 - u;
float magnitue = rb.velocity.magnitude;
float yMag = magnitue * Mathf.Cos(u * Mathf.Deg2Rad);
float xMag = magnitue * Mathf.Cos(v * Mathf.Deg2Rad);
return new Vector2(xMag, yMag);
}
//a lot of math (dont touch)
private void FindWallRunRotation()
{
if (!isWallRunning)
{
wallRunRotation = 0f;
return;
}
_ = new Vector3(0f, playerCam.transform.rotation.y, 0f).normalized;
new Vector3(0f, 0f, 1f);
float num = 0f;
float current = playerCam.transform.rotation.eulerAngles.y;
if (Math.Abs(wallNormalVector.x - 1f) < 0.1f)
{
num = 90f;
}
else if (Math.Abs(wallNormalVector.x - -1f) < 0.1f)
{
num = 270f;
}
else if (Math.Abs(wallNormalVector.z - 1f) < 0.1f)
{
num = 0f;
}
else if (Math.Abs(wallNormalVector.z - -1f) < 0.1f)
{
num = 180f;
}
num = Vector3.SignedAngle(new Vector3(0f, 0f, 1f), wallNormalVector, Vector3.up);
float num2 = Mathf.DeltaAngle(current, num);
wallRunRotation = (0f - num2 / 90f) * wallRunRotateAmount;
if (!useWallrunning)
{
return;
}
if ((Mathf.Abs(wallRunRotation) < 4f && y > 0f && Math.Abs(x) < 0.1f) || (Mathf.Abs(wallRunRotation) > 22f && y < 0f && Math.Abs(x) < 0.1f))
{
if (!cancelling)
{
cancelling = true;
CancelInvoke("CancelWallrun");
Invoke("CancelWallrun", 0.2f);
}
}
else
{
cancelling = false;
CancelInvoke("CancelWallrun");
}
}
private bool IsFloor(Vector3 v)
{
return Vector3.Angle(Vector3.up, v) < maxSlopeAngle;
}
private bool IsSurf(Vector3 v)
{
float num = Vector3.Angle(Vector3.up, v);
if (num < 89f)
{
return num > maxSlopeAngle;
}
return false;
}
private bool IsWall(Vector3 v)
{
return Math.Abs(90f - Vector3.Angle(Vector3.up, v)) < 0.05f;
}
private bool IsRoof(Vector3 v)
{
return v.y == -1f;
}
/// <summary>
/// Handle ground detection
/// </summary>
private void OnCollisionStay(Collision other)
{
int layer = other.gameObject.layer;
if ((int)whatIsGround != ((int)whatIsGround | (1 << layer)))
{
return;
}
for (int i = 0; i < other.contactCount; i++)
{
Vector3 normal = other.contacts[i].normal;
if (IsFloor(normal))
{
if (isWallRunning)
{
isWallRunning = false;
}
grounded = true;
normalVector = normal;
cancellingGrounded = false;
CancelInvoke("StopGrounded");
}
if (IsWall(normal) && (layer == (int)whatIsGround || (int)whatIsGround == -1 || layer == LayerMask.NameToLayer("Ground") || layer == LayerMask.NameToLayer("ground"))) //seriously what is this
{
StartWallRun(normal);
onWall = true;
cancellingWall = false;
CancelInvoke("StopWall");
}
if (IsSurf(normal))
{
surfing = true;
cancellingSurf = false;
CancelInvoke("StopSurf");
}
IsRoof(normal);
}
float num = 3f;
if (!cancellingGrounded)
{
cancellingGrounded = true;
Invoke("StopGrounded", Time.deltaTime * num);
}
if (!cancellingWall)
{
cancellingWall = true;
Invoke("StopWall", Time.deltaTime * num);
}
if (!cancellingSurf)
{
cancellingSurf = true;
Invoke("StopSurf", Time.deltaTime * num);
}
}
private void StopGrounded()
{
grounded = false;
}
private void StopWall()
{
onWall = false;
isWallRunning = false;
}
private void StopSurf()
{
surfing = false;
}
//wallrunning functions
private void CancelWallrun()
{
//for when we want to stop wallrunning
MonoBehaviour.print("cancelled wallrun");
Invoke("GetReadyToWallrun", 0.1f);
rb.AddForce(wallNormalVector * escapeForce);
isWallRunning = false;
}
private void StartWallRun(Vector3 normal)
{
MonoBehaviour.print("wallrunning");
//cancels all y momentum and then applies an upwards force.
if (!grounded && useWallrunning)
{
wallNormalVector = normal;
if (!isWallRunning)
{
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(Vector3.up * initialForce, ForceMode.Impulse);
}
isWallRunning = true;
}
}
private void WallRunning()
{
//checks if the wallrunning bool is set to true and if it is then applies
//a force to counter gravity enough to make it feel like wallrunning
if (isWallRunning)
{
rb.AddForce(-wallNormalVector * Time.deltaTime * moveSpeed);
rb.AddForce(Vector3.up * Time.deltaTime * rb.mass * 40f * wallRunGravity * -Physics.gravity.y);
}
}
}
I used a addForce funktion to add the recoil.Please help me.
This sentence is juist written because i need to add more details
I've made an orthographic camera that is moving by dragging a mouse but can't understand how to create a boundaries for it. It seems that I have to use Mathf.Clamp but can't find out how.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamController : MonoBehaviour
{
public Transform cameraTransform;
public float movementSpeed;
public float movementTime;
public Vector3 newPosition;
public Vector3 dragStartPosition;
public Vector3 dragCurrentPosition;
public Camera cam;
public float maxZoom = 5;
public float minZoom = 20;
public float sensitivity = 1;
public float speed = 30;
float targetZoom;
public float minX = 100;
public float maxX = 120;
// Start is called before the first frame update
void Start()
{
newPosition = transform.position;
}
// Update is called once per frame
void Update()
{
HandleMouseInput();
HandleMovementInput();
{
targetZoom -= Input.mouseScrollDelta.y * sensitivity;
targetZoom = Mathf.Clamp(targetZoom, maxZoom, minZoom);
float newSize = Mathf.MoveTowards(cam.orthographicSize, targetZoom, speed * Time.deltaTime);
cam.orthographicSize = newSize;
}
}
void HandleMouseInput()
{
if (Input.GetMouseButtonDown(0))
{
Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float entry;
if (plane.Raycast(ray, out entry))
{
dragStartPosition = ray.GetPoint(entry);
}
}
if (Input.GetMouseButton(0))
{
Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float entry;
if (plane.Raycast(ray, out entry))
{
dragCurrentPosition = ray.GetPoint(entry);
newPosition = transform.position + dragStartPosition - dragCurrentPosition;
}
}
newPosition = Mathf.Clamp(minX, minX);
}
void HandleMovementInput()
{
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
newPosition += (transform.forward * movementSpeed);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
newPosition += (transform.forward * -movementSpeed);
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
newPosition += (transform.right * movementSpeed);
}
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
newPosition += (transform.right * -movementSpeed);
}
transform.position = Vector3.Lerp(transform.position, newPosition, Time.deltaTime * movementTime);
}
}
newPosition = Mathf.Clamp(minX, minX);
You can't clamp with only two parameters .. you need a current, a min and a max value .. And you can't just convert a float which is what Mathf.Clamp returns into a Vector3 (3 floats)
I think what you meant was rather something like e.g.
newPosition.x = Mathf.Clamp(newPosition.x, minX, maxX);
However, right after that in HandleMovementInput you overwrite it anyway so you might want to change the moment when you are clamping and rather do it right before applying the new position.
Unity script error. The error occurs after adding the "extreme drift" asset.
Here is the mistake itself
"Assets\Extreme Drift\Scripts\Vehicle\VehicleCamera.cs(5,28): error CS0234: The type or namespace name 'ImageEffects' does not exist in the namespace 'UnityStandardAssets' (are you missing an assembly reference?)"
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityStandardAssets.ImageEffects;
public class VehicleCamera : MonoBehaviour
{
public static VehicleCamera manage;
public float smooth = 0.3f;
public float distance = 5.0f;
public float height = 1.0f;
public float angle = 20;
public LayerMask lineOfSightMask = 0;
[HideInInspector]
public Transform target;
[HideInInspector]
public List<Transform> cameraSwitchView;
private bool farCameraView = false;
private Vector3 farCameraPosition;
private Vector3 velocity = Vector3.zero;
private float Xsmooth;
private float farDistance = 0.0f;
private float zAngleAmount = 0.0f;
private float timeScale = 0.0f;
private float currentDistance;
private int Switch = -1;
void Awake()
{
manage = this;
farCameraPosition = transform.position;
}
void Start()
{
farCameraView = true;
farCameraPosition = (AIControl.manage.firstAINode.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode.position)
+ new Vector3(Random.Range(-5.0f, 5.0f), Random.Range(5.0f, 10.0f), Random.Range(-5.0f, 5.0f));
}
void LateUpdate()
{
if (GameUI.manage.gameFinished)
Switch = 4;
farDistance = Vector3.Distance(farCameraPosition, target.position);
if (farDistance < 100.0f && farCameraView) farCameraView = false;
transform.GetComponent<Blur>().enabled = GameUI.manage.gamePaused ? true : false;
// add MotionBlur effect to camera
if (AIControl.CurrentVehicle.shifting || GameUI.manage.driftAmount > 25)
transform.GetComponent<MotionBlur>().blurAmount = Mathf.Lerp(transform.GetComponent<MotionBlur>().blurAmount, 0.5f, Time.deltaTime * 5);
else
transform.GetComponent<MotionBlur>().blurAmount = Mathf.Lerp(transform.GetComponent<MotionBlur>().blurAmount, 0.0f, Time.deltaTime);
if (Switch == -1)
{
RenderSettings.flareStrength = 0.3f;
GetComponent<Camera>().fieldOfView = Mathf.Clamp(AIControl.CurrentVehicle.speed / 10.0f + 60.0f, 60, 90.0f);
currentDistance = distance;
float yAngle = Mathf.SmoothDampAngle(transform.eulerAngles.y,
target.eulerAngles.y, ref velocity.y, smooth);
float xAngle = Mathf.SmoothDampAngle(transform.eulerAngles.x,
target.eulerAngles.x + (angle), ref velocity.x, smooth);
// Look at the target
transform.eulerAngles = new Vector3(xAngle, yAngle, AccelerationAngle());
Xsmooth = Mathf.Lerp(Xsmooth, velocity.y, Time.deltaTime * 10.0f);
var direction = transform.rotation * -new Vector3(-Xsmooth / 300.0f, 0, 1);
var targetDistance = AdjustLineOfSight(target.position + new Vector3(0, height, 0), direction);
transform.position = target.position + new Vector3(0, height, 0) + direction * targetDistance;
}
else if (Switch < AIControl.CurrentVehicle.cameraView.cameraSwitchView.Count)
{
RenderSettings.flareStrength = 0.3f;
GetComponent<Camera>().fieldOfView = 60;
transform.position = cameraSwitchView[Switch].position;
transform.rotation = Quaternion.Lerp(transform.rotation, cameraSwitchView[Switch].rotation, Time.deltaTime * 5.0f);
}
else {
if (farDistance > 120.0f && !farCameraView)
{
farCameraPosition = (AIControl.CurrentVehicle.AIVehicle.nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode
.GetComponent<AINode>().nextNode.position)
+ new Vector3(Random.Range(-5.0f, 5.0f), Random.Range(10.0f, 15.0f), Random.Range(-5.0f, 5.0f));
farCameraView = true;
}
RenderSettings.flareStrength = 0.0f;
GetComponent<Camera>().fieldOfView = Mathf.Clamp(50.0f - (farDistance / 2.0f), 10.0f, 120.0f);
var newRotation = Quaternion.LookRotation(target.position - transform.position);
transform.position = farCameraPosition;
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime * 15);
}
}
public void CameraSwitch()
{
Switch++;
if (Switch > AIControl.CurrentVehicle.cameraView.cameraSwitchView.Count) { Switch = -1; }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private float AccelerationAngle()
{
zAngleAmount = Mathf.Clamp(zAngleAmount, -45.0f, 45.0f);
zAngleAmount = Mathf.Lerp(zAngleAmount, Input.acceleration.x * -70.0f, Time.deltaTime * 2.0f);
return zAngleAmount;
}
float AdjustLineOfSight(Vector3 target, Vector3 direction)
{
RaycastHit hit;
if (Physics.Raycast(target, direction, out hit, currentDistance, lineOfSightMask.value))
return hit.distance;
else
return currentDistance;
}
}
As I understand it, you need to connect the "Standard assets" to the project, I connected it, but it still does not work.
I'm trying to point to an object when it's off-screen. The objects are static.
public class SpawnIndicator : MonoBehaviour
{
public Camera UIcamera;
public GameObject point;
public Canvas canvas;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (point.GetComponent<Renderer>().isVisible)
{
gameObject.GetComponent<SpriteRenderer>().color = Color.clear;
}
else
{
gameObject.GetComponent<SpriteRenderer>().color = Color.white;
//POSITION
Vector3 pointPos = UIcamera.WorldToScreenPoint(point.transform.position);
pointPos.z = 0;
pointPos.x = Mathf.Clamp(pointPos.x, (Screen.width * 0.01f), (Screen.width * 0.99f));
pointPos.y = Mathf.Clamp(pointPos.y, (Screen.height * 0.01f), (Screen.height * 0.99f));
pointPos -= new Vector3((Screen.width/2), (Screen.height/2), 0);
gameObject.transform.localPosition = pointPos;
//ROTATION
gameObject.GetComponent<SpriteRenderer>().color = Color.white;
Vector3 vectorToTarget = point.transform.position - gameObject.transform.position;
float angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
angle -= 90;
Quaternion newRotation = Quaternion.AngleAxis(angle, Vector3.forward);
gameObject.transform.rotation = newRotation;
}
}
}
This works fine when the screen size is 1920x1080 (the reference size for my canvas). However at lower sizes, the objects sit awawy from the edges, and in larger sizes they sit outside of the edges.
Figured it out.
WorldToScreenPoint was returning a value based on the reference resolution (1920x1080) so different resolutions ended up mismatched. I think that's what was going wrong, regardless, I've got the solution.
I found this method to convert a world position to canvas position.
public static Vector3 WorldToScreenSpace(Vector3 worldPos, Camera cam, RectTransform area)
{
Vector3 screenPoint = cam.WorldToScreenPoint(worldPos);
screenPoint.z = 0;
Vector2 screenPos;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(area, screenPoint, cam, out screenPos))
{
return screenPos;
}
return screenPoint;
}
I'd also changed the rest of the code a bit while trying to fix this before finding that solution (and coincidentally was using the canvas size) so here's the full script:
public class SpawnIndicator : MonoBehaviour
{
public Camera UIcamera;
public GameObject point;
public Canvas canvas;
Vector3 pointPos;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (point.GetComponent<Renderer>().isVisible)
{
gameObject.GetComponent<SpriteRenderer>().color = Color.clear;
}
else
{
gameObject.GetComponent<SpriteRenderer>().color = Color.white;
Vector3[] canvasPoints = new Vector3[4];
canvas.GetComponent<RectTransform>().GetLocalCorners(canvasPoints);
Vector3 pointPos = WorldToScreenSpace(point.transform.position, UIcamera, canvas.GetComponent<RectTransform>());
float xMin = canvasPoints[0].x * 0.98f;
float xMax = canvasPoints[2].x * 0.98f;
float yMin = canvasPoints[0].y * 0.8f;
float yMax = canvasPoints[2].y * 0.98f;
//POSITION
if (pointPos.x <= xMin) pointPos.x = xMin;
if (pointPos.x >= xMax) pointPos.x = xMax;
if (pointPos.y <= yMin) pointPos.y = yMin;
if (pointPos.y >= yMax) pointPos.y = yMax;
pointPos.z = 0f;
gameObject.transform.localPosition = pointPos;
//ROTATION
gameObject.GetComponent<SpriteRenderer>().color = Color.white;
Vector3 vectorToTarget = point.transform.position - gameObject.transform.position;
float angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
angle -= 90;
Quaternion newRotation = Quaternion.AngleAxis(angle, Vector3.forward);
gameObject.transform.rotation = newRotation;
}
}
public static Vector3 WorldToScreenSpace(Vector3 worldPos, Camera cam, RectTransform area)
{
Vector3 screenPoint = cam.WorldToScreenPoint(worldPos);
screenPoint.z = 0;
Vector2 screenPos;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(area, screenPoint, cam, out screenPos))
{
return screenPos;
}
return screenPoint;
}
}
I have a touch script to rotate the camera around the orbit. I am facing difficulty to add mouse click and drag function as well more like an || function to this script. The mouse function has Input.GetAxis("Mouse X") which detects the mouse position. How do I achieve it?
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
public float zoomDampening = 5.0f;
public float rotationSensitivity = 1f;
void LateUpdate()
{
if (Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Moved) //Add mouse function
{
Vector2 touchposition = Input.GetTouch(0).deltaPosition;
xDeg += touchposition.x * 20f * 0.002f;
yDeg -= touchposition.y * 20f * 0.002f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.localRotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.localRotation = rotation;
}
I had to add Mouse X and Mouse Y axis to the floating variable and then it works as expected. The addition in the code is given below with the else statement:
else if (Input.GetMouseButton(0)) {
xDeg += Input.GetAxis("Mouse X") * rotationSensitivity;
yDeg -= Input.GetAxis("Mouse Y") * rotationSensitivity;
}
and for anyone who requires the full solution of mouse click and drag/touch and move and zoom in/out:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraOrbit : MonoBehaviour {
public Transform target;
public Vector3 targetOffset;
public float distance = 5.0f;
public float maxDistance = 20;
public float minDistance = .6f;
public float xSpeed = 5.0f;
public float ySpeed = 5.0f;
public int yMinLimit = -80;
public int yMaxLimit = 80;
public float zoomRate = 10.0f;
public float panSpeed = 0.3f;
public float zoomDampening = 5.0f;
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
private Vector3 FirstPosition;
private Vector3 SecondPosition;
private Vector3 delta;
private Vector3 lastOffset;
private Vector3 lastOffsettemp;
public float rotationSensitivity = 1f;
void Start()
{
position = transform.localPosition;
rotation = transform.localRotation;
currentRotation = transform.localRotation;
desiredRotation = transform.localRotation;
distance = Vector3.Distance(transform.position, target.position);
currentDistance = distance;
desiredDistance = distance;
xDeg = Vector3.Angle(Vector3.right, transform.right);
yDeg = Vector3.Angle(Vector3.up, transform.up);
}
void OnEnable() { Init(); }
public void Init()
{
// //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
if (!target)
{
GameObject go = new GameObject("Cam Target");
go.transform.position = transform.position + (transform.forward * distance);
target = go.transform;
}
}
void LateUpdate()
{
if (Input.touchCount == 2 && Input.GetTouch(0).phase == TouchPhase.Moved && Input.GetTouch(1).phase == TouchPhase.Moved)
{
Touch touchZero = Input.GetTouch (0);
Touch touchOne = Input.GetTouch (1);
Vector2 touchZeroPreviousPosition = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePreviousPosition = touchOne.position - touchOne.deltaPosition;
float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude;
float TouchDeltaMag = (touchZero.position - touchOne.position).magnitude;
float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag;
desiredDistance += deltaMagDiff * Time.deltaTime * zoomRate * 0.0025f * Mathf.Abs(desiredDistance);
}
if (Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector2 touchposition = Input.GetTouch(0).deltaPosition;
//CHANGE HERE
xDeg += touchposition.x * xSpeed * 0.002f;
//CHANGE HERE
yDeg -= touchposition.y * ySpeed * 0.002f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
else
if (Input.GetMouseButton(0)) {
xDeg += Input.GetAxis("Mouse X") * rotationSensitivity;
yDeg -= Input.GetAxis("Mouse Y") * rotationSensitivity;
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.localRotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.localRotation = rotation;
////////Orbit Position
// affect the desired Zoom distance if we roll the scrollwheel
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
position = target.position - (rotation * Vector3.forward * currentDistance );
position = position - targetOffset;
transform.position = position;
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}