Using the Touch inputs I know how to drag a gameobject. But what I need to do is to (upon release of drag) check the speed of the drag and have the object move a bit further. So if I drag the object fast and release it it will move a bit in the dragged direction after releasing it. As it is now it simply stops at the position where I remove my finger. Anyone know how this is done?
What I have now is:
private Vector3 dist, distEnd;
float posX;
float posY;
void OnMouseDown() {
dist = Camera.main.WorldToScreenPoint (transform.position);
posX = Input.mousePosition.x - dist.x;
posY = Input.mousePosition.y - dist.y;
}
void OnMouseDrag()
{
Vector3 curPos = new Vector3 (Input.mousePosition.x - posX, Input.mousePosition.y - posY, dist.z);
Vector3 worldPos = Camera.main.ScreenToWorldPoint (curPos);
transform.position = worldPos;
}
void OnMouseUp() {
distEnd = Camera.main.WorldToScreenPoint (transform.position);
}
Then I added a RigidBody2d to the object - trying to add force to it - but I suppose I need to calculate the speed and direction of drag/mouse - before I can add directional force to the object??
GetComponent<Rigidbody2D> ().AddForce (Vector2 (FORCE_DIRECTION_X, FORCE_DIRECTION_Y));
But I'm having difficulties calculating direction and speed of drag.
Any help is appreciated!
Thanks.
Right, I finally found an answer :-) I have included a script for others to use (I did not come up with the solution though).
Maybe someone could use it as well - alter variable "SmoothTime" so set time before drag-speed is 0.
using UnityEngine;
using System.Collections;
public class dragMap : MonoBehaviour {
private Vector3 _screenPoint;
private Vector3 _offset;
private Vector3 _curScreenPoint;
private Vector3 _curPosition;
private Vector3 _velocity;
private bool _underInertia;
private float _time = 0.0f;
public float SmoothTime = 2;
void Update()
{
if(_underInertia && _time <= SmoothTime)
{
transform.position += _velocity;
_velocity = Vector3.Lerp(_velocity, Vector3.zero, _time);
_time += Time.smoothDeltaTime;
}
else
{
_underInertia = false;
_time = 0.0f;
}
}
void OnMouseDown()
{
_screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
_offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, _screenPoint.z));
//Screen.showCursor = false;
_underInertia = false;
}
void OnMouseDrag()
{
Vector3 _prevPosition = _curPosition;
_curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _screenPoint.z);
_curPosition = Camera.main.ScreenToWorldPoint(_curScreenPoint) + _offset;
_velocity = _curPosition - _prevPosition;
transform.position = _curPosition;
}
void OnMouseUp()
{
_underInertia = true;
//Screen.showCursor = true;
}
}
Related
I´ve followed a youtube tutorial https://www.youtube.com/watch?v=c1FYp1oOFIs&list=PLD_vBJjpCwJtrHIW1SS5_BNRk6KZJZ7_d&index=4
and the problem is when i start the game my camera moves up when it shouldnt.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BARR3TT
{
public class CameraHandler : MonoBehaviour
{
public Transform targetTransform;
public Transform cameraTransform;
public Transform cameraPivotTransform;
private Transform myTransform;
private Vector3 cameraTransformPosition;
private LayerMask ignoreLayers;
private Vector3 cameraFollowVelocity = Vector3.zero;
public static CameraHandler singleton;
public float lookSpeed = 0.1f;
public float followSpeed = 0.1f;
public float pivotSpeed = 0.03f;
private float targetPosition;
private float defaultPosition;
private float lookAngle;
private float pivotAngle;
public float minimumPivot = -35;
public float maximumPivot = 35;
private float cameraSphereRadius = 0.2f;
public float cameraColisionOffset = 0.2f;
public float minimumColisionOffset = 0.2f;
private void Awake()
{
singleton = this;
myTransform = transform;
defaultPosition = cameraTransform.localPosition.z;
ignoreLayers = ~(1 << 8 | 1 << 9 << 10);
}
public void FollowTarget(float delta)
{
Vector3 targetPosition = Vector3.SmoothDamp(myTransform.position, targetTransform.position, ref cameraFollowVelocity, delta / followSpeed);
myTransform.position = targetPosition;
HandleCameraCollision(delta);
}
public void HandleCameraRotation(float delta, float mouseXInput, float mouseYInput)
{
lookAngle += (mouseXInput * lookSpeed) / delta;
pivotAngle -= (mouseYInput * pivotSpeed) / delta;
pivotAngle = Mathf.Clamp(pivotAngle, minimumPivot, maximumPivot);
Vector3 rotation = Vector3.zero;
rotation.y = lookAngle;
Quaternion targetRotation = Quaternion.Euler(rotation);
myTransform.rotation = targetRotation;
rotation = Vector3.zero;
rotation.x = pivotAngle;
targetRotation = Quaternion.Euler(rotation);
cameraPivotTransform.localRotation = targetRotation;
}
private void HandleCameraCollision(float delta)
{
targetPosition = defaultPosition;
RaycastHit hit;
Vector3 direction = cameraTransform.position - cameraPivotTransform.position;
direction.Normalize();
if(Physics.SphereCast(cameraPivotTransform.position, cameraSphereRadius, direction, out hit ,Mathf.Abs(targetPosition)))
{
float dis = Vector3.Distance(cameraPivotTransform.position, hit.point);
targetPosition = -(dis - cameraColisionOffset);
}
if(Mathf.Abs(targetPosition)<minimumColisionOffset)
{
targetPosition = -minimumColisionOffset;
}
cameraTransformPosition.z = Mathf.Lerp(cameraTransform.localPosition.z, targetPosition, delta / 0.2f);
cameraTransform.localPosition = cameraTransformPosition;
}
}
}
Ive checked every line and i dont see any mistakes the transforms are where they should be, i can kinda fix it adding some rotation in the x axis on the main camera but its still weird
You need to check if your camera has been attached to any script or if it is a child inside some objects. I think it is where the error comes from.
If the Camera Holder or Camera Pivot changes its direction so the Main Camera will be changed too.
Your code is very complicated and it doesn't have any comments. So that is why people when seeing your code are lazy to see, analyze and answer for you.
If you just begin with coding and I recommend that you need to build a good foundation first and then go to some difficult tutorials like those you followed. Don't follow step-by-step tutorials.
I am working on a 2d zombie killing game but there was an error rotating the gun in my code, when I rotate the gun it turns wrong. Can you help me?
Video:https://youtu.be/8kUgXkEZc2M
Here is the code:
[SerializeField] Transform _arm;
float _offset = -90;
Vector3 _startingSize;
Vector3 _armStartingSize;
public GameObject Bullet;
public float BulletSpeed;
public Transform ShootPoint;
#region Start
// Start is called before the first frame update
void Start()
{
_startingSize = transform.localScale;
_armStartingSize = _arm.localScale;
}
#endregion
// Update is called once per frame
void Update()
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 perendicular = _arm.position - mousePos;
Quaternion val = Quaternion.LookRotation(Vector3.forward, perendicular);
val *= Quaternion.Euler(0, 0, _offset);
_arm.rotation = val;
if(transform.position.x - mousePos.x < -0.1)
{
transform.localScale = _startingSize;
_arm.localScale = _armStartingSize;
}
else if(transform.position.x - mousePos.x > 0.1)
{
transform.localScale = new Vector3(-_startingSize.x, _startingSize.y, _startingSize.z);
_arm.localScale = new Vector3(-_armStartingSize.x, -_armStartingSize.y, _armStartingSize.z);
}
if (Input.GetMouseButtonDown(0))
{
shoot();
}
}
void shoot()
{
cineShake.Instance.ShakeCamera(5f, .1f);
GameObject BulletIns = Instantiate(Bullet, ShootPoint.position, ShootPoint.rotation);
BulletIns.GetComponent<Rigidbody2D>().AddForce(BulletIns.transform.right * BulletSpeed);
}
I am trying to move an object with mouse or touch but on particular fixed curve path after selecting an object.
I created a fixed path using bezier curve, and movement of object in path is working fine if i am using keyboard inputs using Input.GetAxisRaw("Horizontal"), but i want to based on mouse drag or touch.
using System;
using UnityEngine;
public class Collector : MonoBehaviour
{
public Transform startPoint;
public Transform middlePoint;
public Transform endPoint;
public float curveSpeed = 0.5f;
//public float speed = 0f;
private int _direction = 1;
private bool _isObjectSelected;
private Vector3 _mouseLastPosition;
private float _journeyLength;
private Vector3 _offsetPos;
private float _currentTime = 0;
private void Start()
{
_journeyLength = Vector3.Distance(startPoint.position,
endPoint.position);
UpdateJourney(0);
}
private void OnMouseDown()
{
if (_isObjectSelected)
return;
_offsetPos = Vector3.zero;
_mouseLastPosition = Input.mousePosition;
_isObjectSelected = true;
}
private void OnMouseUp()
{
_isObjectSelected = false;
}
private void OnMouseExit()
{
_isObjectSelected = false;
}
private void OnMouseDrag()
{
if (_isObjectSelected)
{
Debug.LogError("Mouse drag");
Vector3 currentPosition = Input.mousePosition;
_offsetPos += currentPosition - _mouseLastPosition;
float distCovered = _offsetPos.y / _journeyLength;
UpdateJourney(distCovered);
_mouseLastPosition = currentPosition;
}
}
private void UpdateJourney(float time)
{
if (time < 0)
time = 0;
else if (time > 1)
time = 1;
_currentTime = time;
transform.position =
QuadraticCurve(startPoint.position,
middlePoint.position,
endPoint.position,
_currentTime);
transform.rotation = Quaternion.Euler(
new Vector3(0, 0,
QuadraticCurve(0, 45, 90, _currentTime)));
}
private void Update()
{
// moving on path using keyboard input
float direction = Input.GetAxisRaw("Horizontal");
if (Math.Abs(direction) > 0.1f)
{
_currentTime += Time.deltaTime * curveSpeed * direction;
UpdateJourney(_currentTime);
}
}
private static Vector3 Lerp(Vector3 start, Vector3 end, float time)
{
return start + (end - start) * time;
}
private static Vector3 QuadraticCurve(Vector3 start, Vector3 middle, Vector3 end, float time)
{
Vector3 point0 = Lerp(start, middle, time);
Vector3 point1 = Lerp(middle, end, time);
return Lerp(point0, point1, time);
}
private static float QuadraticCurve(float start, float middle, float end, float time)
{
float point0 = Mathf.Lerp(start, middle, time);
float point1 = Mathf.Lerp(middle, end, time);
return Mathf.Lerp(point0, point1, time);
}
}
There are a few issues:
You have a Debug.LogError. You shouldn't do this since usually this interrupts the execution. By default the ErrorPause option in the Unity console is enabled. You should either remove this entirely (since Debug.Log in Update in general are very perfomance intense).
One of the main issues here will be that the dragged object does not stay under the mouse but ruther follows the given curve. Therefore, OnMouseExit will get called and OnMouseDrag is interrupted.
You can also simply keep track of the traveled distance using the mouse start position and compare it to the current one. No need for additionally increase a third variable.
I would therefore rather change the code and use
private Vector3 _mouseStartPosition;
// remove OnMouseExit
// remove OnMouseUp
// remove OnMouseDrag
private void OnMouseDown()
{
if (_isObjectSelected) return;
_mouseStartPosition = Input.mousePosition;
_isObjectSelected = true;
}
private void WhileDragging()
{
if (!_isObjectSelected) return;
//Debug.LogError("Mouse drag");
var currentPosition = Input.mousePosition;
var offsetPos = currentPosition - _mouseStartPosition;
// You might want to use the curveSpeed here as well
// like kind of sensitivity
var distCovered = offsetPos.y * curveSpeed / _journeyLength;
UpdateJourney(distCovered);
}
// instead of using OnMouseExit, OnMouseUp and OnMouseDrag rather
// do it in Update
private void Update()
{
if (_isObjectSelected)
{
// use this to detect mouse up instead
if (Input.GetMouseButtonUp(0))
{
_isObjectSelected = false;
}
}
// call it here instead of using OnMouseDrag
WhileDragging();
...
}
Note: This of course still only uses the traveled distance in Y direction. If you rather wanted to get the closest point on the bezier curves this gets a lot more complex and you might want to look it up (Nearest point on cubic bezier curve to a given point, Nearest point on a quadratic bezier curve, Closest point on Bezier spline, etc ...)
Thanks #derHugo,
I will try to resolve the problem with this (Nearest point on cubic bezier curve to a given point, Nearest point on a quadratic bezier curve, Closest point on Bezier spline, etc ...)
although i want a simple solution instead of complex code.
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = _mainCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
if (hit.transform.gameObject == this.gameObject)
{
_mouseStartPosition = _mainCamera.ScreenToWorldPoint(Input.mousePosition);
_isObjectSelected = true;
}
}
}
if (Input.GetMouseButtonUp(0))
{
if (_isObjectSelected)
{
_isObjectSelected = false;
//Debug.LogError("Gettting false");
}
}
if (_isObjectSelected)
{
Vector3 mousePosition = _mainCamera.ScreenToWorldPoint(Input.mousePosition);
mousePosition.z = 0f;
//Debug.LogError(mousePosition + " , " + transform.position);
Vector3 distanceVector = mousePosition - _mouseStartPosition;
float distance = distanceVector.magnitude;
Vector3 normalDistance = distanceVector.normalized;
//Debug.LogError(distance + " " + normalDistance);
if (distance > 0.1f)
{
if (normalDistance.y > 0.1f)
{
_currentTime -= Time.deltaTime * distance * 3f;
_shieldMovement.UpdateJourney(_currentTime);
}
else if (normalDistance.x > 0.1f)
{
_currentTime += Time.deltaTime * distance * 3f;
_shieldMovement.UpdateJourney(_currentTime);
}
}
_mouseStartPosition = mousePosition;
}
so far, i did this in update method, its not perfect but working ok.
I'm trying to get the distance between my player, and the nearest object with the tag 'wall' however I can't seem to get it to work.
To my knowledge my code isn't working at all.
So my question is;
What am I doing wrong? Again, I want to find the distance from my player and the nearest object with the tag 'wall'. If I'm near a object with the tag 'wall' I want it to set the variable to true.(nearWall = true) then once I'm away from the object(About 10.0f) I want it back to false.(nearWall = false)
This is the code I have been working with.
using UnityEngine;
using System.Collections;
public class PlayerMotor : MonoBehaviour {
private CharacterController controller;
private Vector3 moveVector;
private float speed = 2.0f;
private float verticalVelocity = 0.0f;
private float gravity = 12.0f;
private bool nearWall;
public GameObject playerObject;
GameObject closestObject;
float distance = Mathf.Infinity;
public float distanceToWall = Mathf.Infinity;
private void Start() {
nearWall = false;
playerObject = GameObject.Find("Player");
distanceToWall = 0;
controller = GetComponent<CharacterController> ();
}
public void getNearestWall()
{
if (distance <= 10.0f) {
nearWall = true;
print ("Near wall!");
}
else
nearWall = false;
}
GameObject findNearestWall()
{
GameObject[]objectArray;
objectArray = GameObject.FindGameObjectsWithTag("wall");
Vector3 position = playerObject.transform.position;
foreach(GameObject currentObject in objectArray)
{
Vector3 distanceCheck = currentObject.transform.position - position;
float currentDistance = distanceCheck.sqrMagnitude;
if (currentDistance < distance)
{
closestObject = currentObject;
distance = currentDistance;
}
}
return closestObject;
}
private void Update()
{
findNearestWall ();
moveVector = Vector3.zero;
if (controller.isGrounded)
{
verticalVelocity = -0.5f;
}
else
{
verticalVelocity -= gravity * Time.deltaTime;
}
if (Input.GetMouseButton (0)) {
if (!nearWall) {
if (Input.mousePosition.x > Screen.width / 2)
moveVector.x = speed;
else
moveVector.x = -speed;
}
else
{
moveVector.x = transform.forward.x * speed;
transform.Rotate(new Vector3(0, -90, 0));
}
}
moveVector.y = verticalVelocity;
moveVector.z = transform.forward.z * speed;
controller.Move (moveVector * Time.deltaTime);
}
}
One thing is that you are not calling getNearestWall() method - which is actually changing the flag - anywhere.
And second why don't you just try:
currentDistance = Vector3.Distance(currentObject.transform.position, position);
When calculating distance
first of all you need to call getNearestWall(); inside the Update() method ( after findNearestWall() of course ). also what you are doing now is getting the minimal distance the player reached in the whole game. you might want to add distance = Mathf.Infinity; in top of findNearestWall() so it will something like this:
GameObject findNearestWall()
{
GameObject[] objectArray;
objectArray = GameObject.FindGameObjectsWithTag("wall");
distance = Mathf.Infinity;
Vector3 position = playerObject.transform.position;
foreach (GameObject currentObject in objectArray)
{
Vector3 distanceCheck = currentObject.transform.position - position;
float currentDistance = distanceCheck.sqrMagnitude;
if (currentDistance < distance)
{
closestObject = currentObject;
distance = currentDistance;
}
}
return closestObject;
}
now whenever you get near a wall it should print Near wall!
note:
also you are calling FindObjectsWithTag() at an Update method which might significantly drain your processing power. you might want to avoid that by declaring a private GameObject[] objectArray in the class.
and then use objectArray = GameObject.FindGameObjectsWithTag("wall"); once at Awake() or Start()
So here's the problem in video form
https://pbs.twimg.com/tweet_video/CPsvjgbWoAACKCp.mp4
When not moving the ship the shield moves around just fine, but when you start moving it can only drag behind you and move a little bit, which is just no good at all. I can't figure out what I've done wrong here!
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
public float circSpeed = 0.1f; // Speed Shield moves around ship
private Vector3 direction = Vector3.up;
private float distance = 0.8f; // distance from player so it doesn't clip
private float deadzone = 0.15f;
private float separation;
private bool canMove = true;
private Vector3 shipPos;
private Rigidbody2D tRB;
private Rigidbody2D rb;
// Use this for initialization
void Start ()
{
tRB = target.GetComponent<Rigidbody2D>();
rb = GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D (Collision2D other)
{
canMove = false;
}
void OnCollisionStay2d(Collision2D other)
{
canMove = false;
}
void OnCollisionExit2D (Collision2D other)
{
canMove = true;
}
// Update is called once per frame
void Update () {
float rh = Input.GetAxisRaw("rightH");
float rv = Input.GetAxisRaw("rightV");
shipPos = target.position;
separation = Mathf.Abs((transform.position - shipPos).magnitude);
if(Mathf.Abs(rh) > deadzone || Mathf.Abs(rv) > deadzone)
{
Vector3 targetDir = new Vector3(rh, rv, 0.0f);
direction = Vector3.Slerp(transform.position-shipPos, targetDir, circSpeed);
}
Ray ray = new Ray(shipPos, direction); // cast ray in direction of point on circle shield is to go
if(canMove)
{
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the distance
}
if(separation != distance) //If the shield get torn away from the ship
{
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the distance
}
float angleY = transform.position.y - shipPos.y;
float angleX = -(transform.position.x - shipPos.x);
float angle = Mathf.Atan2 (angleY, angleX) * Mathf.Rad2Deg-90; //Get angle
if(Mathf.Abs(rh) > deadzone || Mathf.Abs(rv) > deadzone)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1); // keep shield facing outwards in respect to player
}
}
void FixedUpdate ()
{
if(!canMove)
{
tRB.velocity = new Vector2(0.0f, 0.0f);
rb.velocity = new Vector2(0.0f, 0.0f);
}
}
Thanks a million for any help :)
You need to move the shield along with the ship. You can do this by adding the ship velocity to the shield.
Something like:
shipPos = target.position;
transform.position += shipVelocity;
separation = Mathf.Abs((transform.position - shipPos).magnitude);
Or make the shield a child object of the ship.
OK, so all I needed to do was to make the shield a child AND get rid of the conditional statement around the transform.rotation so it wouldn't inherit the parent rotation and ruin the shield. It's the little things!