How to slow down rotation? - c#

So I wrote some code to make an object rotate if I swiped left or right
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotater : MonoBehaviour {
public Transform player;
void Update()
{
if (Input.touchCount == 1)
{
// GET TOUCH 0
Touch touch0 = Input.GetTouch(0);
// APPLY ROTATION
if (touch0.phase == TouchPhase.Moved)
{
player.transform.Rotate(0f, 0f, touch0.deltaPosition.x);
}
}
}
}
and the problem is when I swipe fast the rotation will be uncontrollable. So I want the input to be less sensitive.
my goal is for the rotation to be like rolly vortex
my setup:
I made an empty object and put it in the center
made the empty object a parent of my player
and finally, I put my code in the empty object
this setup made the player rotate in sort of an orbit which like I told you is similar to rolly vortex.

First you want to be able to scale the sensitivity. This means making it so that for every unit of change in touch position, you will get some multiple of a unit of change in the rotation. For this, make a configurable (public) member variable, public float touchSensitivityScale, and multiply the rotation by that value. Example:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotater : MonoBehaviour {
public Transform player;
public float touchSensitivityScale;
void Update()
{
if (Input.touchCount == 1)
{
// GET TOUCH 0
Touch touch0 = Input.GetTouch(0);
// APPLY ROTATION
if (touch0.phase == TouchPhase.Moved)
{
player.transform.Rotate(0f, 0f, touch0.deltaPosition.x * touchSensitivityScale);
}
}
}
}
Now you can edit the touch sensitivity in the inspector. With touchSensitivityScale set to 1, the behavior will be identical to what it is currently. If you make the number 0.5, the rotation will be half as sensitive.
If this doesn't fully solve the problem and you also want some smoothing or acceleration, that might warrant an edit to the question.
I hope it helps!

Rather than rotating by touch0.deltaPosition.x you could always have some sort of negative exponential function. In this case it’d probably be something along the lines of e^(-x-a) where x is your touch0.deltaPosition.x, and a would be a variable you’d have to determine based on how fast you want the initial speed of rotation. If you’re not familiar with exponential functions try using a graphing software like Desmos to plot y=e^(-x-a) and vary the value of a. Once you’ve visualised that it should be pretty self explanatory.

Related

Calculating force of a rigidbody depending on how far away it is from a center of another game object? [duplicate]

This question already has answers here:
Unity: AddExplosionForce to 2D
(3 answers)
Closed 7 months ago.
Currently making a Unity 2D game that includes rocket jumping (e.g TF2, Quake). I have successfully created the code that launches the player in the correct direction depending on the position of an explosion prefab (which is just a circle). I wish to implement a multiplier that changes the applied force depending on the player's distance from the explosion.
I've experimented with using Vector2.Distance but I have had no luck thinking of ways to convert this into a meaningful value.
Here's my current code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandleExplosion : MonoBehaviour
{
[SerializeField] float launchSpeed;
[SerializeField] float explosionTime;
private void Start()
{
StartCoroutine(DeleteExplosion());
}
private void OnCollisionEnter2D(Collision2D player)
{
if (player.gameObject.CompareTag("Player"))
{
Debug.Log(CalculateForceMultiplier(player));
Vector2 launchPos = player.transform.position - transform.position;
player.gameObject.GetComponent<Rigidbody2D>().AddForce(launchPos * launchSpeed * CalculateForceMultiplier(player), ForceMode2D.Impulse);
}
}
float CalculateForceMultiplier(Collision2D player)
{
return Vector2.Distance(player.transform.position, transform.position);
}
IEnumerator DeleteExplosion() {
yield return new WaitForSeconds(explosionTime);
Destroy(gameObject);
}
}
float CalculateForceMultiplier(Collision2D)
{
Vector2 _dist = Vector2.Distance(player.transform.position, transform.position);
return _dist != 0 ? 1f / _dist : 100f;
}
In your code, the method returned the distance between the explosion and the player.
By doing this, the farther away the player is, the larger the return value will be, and the closer it is, the smaller it will be, which I intuitively think is the opposite of what you want.
In the method I wrote I check if the distance between the explosion and the player is different from 0 and if it is true I return 1 / the distance, i.e. the closer it is, the closer the returned value will be the greater, while the farther away the more the returned value will be close to 0.
If the two objects are in the same position, trying to divide 1 / the distance, that is 0, you would get an exception, so if this happens I set a very large value to be returned because the power would ideally be maximum.

Unity 3d GO orientation

I look for the best way to detect, what site of an GO (cube) is facing upwards.
My research led me to the Dot-product.
I know what I want to do, but I guess my c# skills are too bad..
Basically I just want to find the Dot-product for example for the x-rotation.
And if its between a value of 0,9 to 1 one site is facing upwards, for -0,9 to -1 the other Site and so on for all axes.
In the Unity's documentation you have the following example. You just have to tweak it a little bit in order to achieve what you need.
// detects if other transform is behind this object
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public Transform other;
void Update()
{
if (other)
{
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 toOther = other.position - transform.position;
if (Vector3.Dot(forward, toOther) < 0)
{
print("The other transform is behind me!");
}
}
}
}

How can I check the distance from each one of the cubes depending on what cube I'm closer to?

The cubes are in formation of a big square to create some kind of border so the player can't move further.
transform is the player the script is attached to the player.
When I move the player to one of the cubes close to it the distance is about 95 but it should 0.1f or 0.
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityStandardAssets.Characters.ThirdPerson;
public class DistanceCheck : MonoBehaviour
{
public Transform[] cubes;
public GameObject descriptionTextImage;
public TextMeshProUGUI text;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
for (int i = 0; i < cubes.Length; i++)
{
var dist = Vector3.Distance(transform.position, cubes[i].transform.position);
if (dist <= 0.1f)
{
descriptionTextImage.SetActive(true);
text.text = "I can't move.";
}
else
{
text.text = "";
descriptionTextImage.SetActive(false);
}
}
}
}
When I'm using a break point on the line :
if (dist <= 0.1f)
dist is a bit more then 95. Maybe the distance is checked to another cube or in another point on the cube?
You are checking all cubes every time and using same "dist" variable every time.
So it detects deistance being less then 0.1f, but goes on and changes value of dist to test another cube.This is why you are getting higher values despite being right next to a cube.
You need 4 distance variables that are each measuring distances to its specific cube and do something if either of them gets too short.
Another flaw is that you are measuring distance to a point in a box, so depending which side of a box you are its going to be showing different values.
I would suggest instead of using cube Transforms, use their Colliders instead. And then I'd be looking for the closest point on the collider bounds. As it currently stands, you're checking for the distance of this object, to the origin of the cube, and it sounds to me like you simply want to find the distance to the cube/collider in general.
First, change the field type for your cubes:
public BoxCollider[] cubes;
Then find the distance like this:
var closestPoint = cubes[ i ].ClosestPointOnBounds ( transform.position );
var distance = Vector3.Distance( transform.position, closestPoint );
Now you should be getting a distance to the closest point to the cube/collider.
More information on ClosestPointOnBounds can be found here at the Unity docs.

Questions arising from first-person controller code in Unity

I am creating a first person controller in Unity. Very basic stuff, camera is a child of Player capsule. Codes work, but I need help explaining what's going on.
*camera is child of Player in hierarchy
These are my questions:
In PlayerMovement, why are we translating in the Z-axis to achieve vertical movement when Unity is in Y-Up axis?
In CamRotation, I have no idea what is going on in Update(). Why are we applying horizontal movement to our Player, but then vertical movement to our Camera? Why is it not applied on the same GameObject?
What is mouseMove trying to achieve? Why do we use var?
I think we are getting a value of how much mouse has been moved, but what then does applying Vector2.Scale do to it?
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
public float speed = 5.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float mvX = Input.GetAxis("Horizontal") * Time.deltaTime * speed;
float mvZ = Input.GetAxis("Vertical") * Time.deltaTime * speed;
transform.Translate(mvX, 0, mvZ);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamRotation : MonoBehaviour {
public float horizontal_speed = 3.0F;
public float vertical_speed = 2.0F;
GameObject character; // refers to the parent object the camera is attached to (our Player capsule)
// initialization
void Start()
{
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update()
{
var mouseMove = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
mouseMove = Vector2.Scale(mouseMove, new Vector2(horizontal_speed, vertical_speed));
character.transform.Rotate(0, mouseMove.x, 0); // to rotate our character horizontally
transform.Rotate(-mouseMove.y, 0, 0); // to rotate the camera vertically
}
}
XY is the plane for 2D Unity games. For 3D, you have Z-axis for height, and XY plane for positioning.
Note that different components from mouseMove are being applied (.x for character and .y for the camera). This means that the movement from the character is not equal to the movement from the camera; one should be faster/slower than the other.
var is a predefined C# keyword that lets the compiler figure out an appropriate type. In this case, it's the same as if you had written Vector2 as in Vector2 mouseMove = new Vector2(...);.
You are scaling the value from mouseMove, by multiplying its components by predefined values in your code. That's just it.
EDIT
You apply .x to your character because, as you commented after the line of code, you want to move it horizontally. As for the camera, .y is being applied because you want to move it vertically.
The negative value could be because the axis is inverted, so you make it negative so the camera has a natural movement. It's the same principle some games have in the setting, where they allow you to invert Y-axis.

Declare gameObject to animate

I have a tutorial scene where you go through the level and reach a certain door, when you collide with that, it disables a canvas at the top, and animates the door. I've searched everywhere in the Scripting Docs, but can't find the solution. What type of variable do you declare the object to animate?
I tried declaring public GameObject/Transform UIQuest and UIQuest.Animation.Play("DoorOpen"), but it comes up with the error of not having the Animation in the API for that. Am I just doing this completely wrong or is there something simple I'm missing?
Complete script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class DoorOpen : MonoBehaviour {
public GameObject door;
public Canvas UIQuest;
void Start () {
}
void Update () {
}
void OnCollisionEnter(Collision doorCollision)
{
if (doorCollision.gameObject.name == "Door")
{
door.Animation.Play("DoorOpen");
UIQuest.enabled = false;
}
}
}
As the gameobject is only performing a simple animation you do not need anything special (such as an AnimationController), you simply need to perform a rotation of the door over time, set the pivot of the door to the edge and rotate the door along the y-axis when conditions are met (i.e. when a collision is detected).
Something like :
gameobject.transform.Rotate(0, rotationAmount * Time.DeltaTime, 0);
You will also need logic to decide when to stop the rotation (i.e. when the door is fully open) unless you want a revolving doorway. Also if the door is just a sliding door this is even easier as you perform a translate instead of a rotate.

Categories