Jittery movement with falling object moving back and forth horizontally - unity3d

I've got a falling object, which i want to move back and forth horizontally while falling.
While i've manage to do this, i'm getting a jittery movement while this happens. When the object falls without horizontal movement, theres no jittery movement.This is also the case if the object just moves horizontally without falling.
I'm currently using rigidbody2d.velocity to move it horizontally and have tried using transform.position and translate but didn't see any difference in smoother movement.
Jittery Movement GIF
So clearly theres an issue with combine the two movements together, but i can't work out how to remedy this in order to make it a smooth movement.
Object Inspector Image
Here's the object code for it's movement:
public float verticalSpeed = 7f;
private Rigidbody2D object_RB;
private int moveHorizontal;
private int horizontalSpeed;
void Start()
{
object_RB = GetComponent<Rigidbody2D>();
moveHorizontal = Random.Range(1, 3);
horizontalSpeed = Random.Range(4, 7);
}
void Update()
{
if (transform.position.y <= -10f)
{
Destroy(gameObject);
}
if (transform.position.x < -1.7f)
{
moveHorizontal = 1;
}
else if (transform.position.x > 1.7f)
{
moveHorizontal = 2;
}
transform.position -= transform.up * Time.deltaTime * verticalSpeed;
}
void FixedUpdate()
{
if (moveHorizontal == 1)
{
object_RB.velocity = new Vector2(horizontalSpeed, 0);
}
else if (moveHorizontal == 2)
{
object_RB.velocity = new Vector2(-horizontalSpeed, 0);
}
}
I'm stuck with this and would appreciate some input to fix this movement.
EDIT - I've tried setting the Interpolate property of the rigidbody to Interpolate or Extrapolate and had no luck. If i set it to Interpolate, the horizontal movement slows down drastically, to a point where it doesn't seem like its moving horizontally at all. Changing it to Extrapolate actually increases the jittery effect.

Related

How to move 2d Rigidbody Smoothly to Mouse on Click

Vector2 mousePos = Input.mousePosition;
// motion core
if (GameObject.Find("Camera").GetComponent<room>().playerNum == 1)
{
if (Input.GetMouseButtonDown(0))
{
// move script not working
}
}
So, I have mostly every possible solution I could find but none of them worked. I cannot get it to smoothly move with AddForce because I could not figure out a working algorithm to make the force move toward the MousePosition.
The position you're getting out of Input.mousePosition are the coordinates on the screen, not the position in the world. To transform between the two, you can use Camera.ScreenToWorldPoint().
if (Input.GetMouseButtonDown(0))
{
Vector3 mousePos = Input.mousePosition
mousePos = new Vector3(mousePos.x, mousePos.y, Camera.main.nearClipPlane)
Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3())
// move script
}
You might need to edit the z coordinate in the mousePos to the current transform.position.z of the object you're trying to move, or another value that makes most sense here. It acts as a kind of wall, where it'll create the point exactly that far from the camera on your mouse position. This should be a lot cheaper than raycasting, and still works if there's nothing to hit where you're clicking.
I have a script that did this same movement to the handle of a wrecking ball, but I don't have the code with me at the moment. I can't remember exactly how it worked, but I think the idea was that when the mouse was clicked, drag would be set to a very high number and gravity would be set to 0. Then an extremely strong force would be added to counter the drag so that the object would fly towards the mouse without orbiting. When the mouse was released, the drag and gravity would be set back to normal.
I can't test this at the moment because I'm on a chromebook and my PC with Unity on it is in another building, but this code should do the trick if I don't make any errors.
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
float prevDrag, prevGrav;
bool mousedown;
Plane plane;
Rigidbody2D r;
void Start()
{
r = GetComponent<Rigidbody2D>(); // assuming this script is attached to the object being moved.
plane = new Plane(Vector3.up, Vector3.zero);
}
void Update()
{
if(mousedown)
{
float enter;
if (plane.Raycast(ray, out enter))
{
var hitPoint = ray.GetPoint(enter);
var mouseDir = hitPoint - gameObject.transform.position;
rb.AddForce(mouseDir * 9999999);
}
}
}
void OnMouseDown()
{
mousedown = true;
prevDrag = r.drag;
prevGrav = r.gravity;
r.drag = 99999;
r.gravity = 0;
}
void OnMouseUp()
{
mousedown = false;
r.drag = prevDrag;
r.gravity = prevGrav;
}
}

Rotate Bar Based on Touch Drag

I want to rotate the bar based on my finger touch draw related to the pivot point. Following test structure implementation, I have created it for testing purposes.
Currently, I can able to write this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestRotateController : MonoBehaviour
{
float rotateSpeed = 10f;
Vector2 touchStartPos;
Transform touchItem;
//
[SerializeField] LayerMask touchItemsMask;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 mousePos2D = new Vector2(mousePos.x, mousePos.y);
RaycastHit2D hit = Physics2D.Raycast(mousePos2D, Vector2.zero, 0f, touchItemsMask);
if (hit.collider != null && hit.transform.CompareTag(GameConstants.TAG_RELEASE_ANGLE_BAR))
{
touchItem = hit.transform;
touchStartPos = mousePos2D;
}
}
else if (Input.GetMouseButton(0))
{
if (touchItem != null && touchItem.CompareTag(GameConstants.TAG_RELEASE_ANGLE_BAR))
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 mousePos2D = new Vector2(mousePos.x, mousePos.y);
RotateReleaseAngleBar(touchStartPos, mousePos2D);
}
}
else if (Input.GetMouseButtonUp(0))
{
touchItem = null;
}
}
// rotate pivot parent
public void RotateReleaseAngleBar(Vector2 touchStartPosition, Vector2 touchPosition)
{
if (touchStartPosition.x > touchPosition.x)
{
transform.parent.Rotate(Vector3.forward, rotateSpeed * Time.deltaTime);
}
else if (touchStartPosition.x < touchPosition.x)
{
transform.parent.Rotate(Vector3.forward, -rotateSpeed * Time.deltaTime);
}
}
}
Now with this code, I can't able to rotate the bar as my finger is moving.
Selected direction will remain proper because I have used X value to decide this but when I stop dragging my finger then also rotation remain continue in the same direction.
I want to stop this, I want to rotate the bar based on finger drag amount. It is a kind of experience, I want a person is rotating the bar with his finger.
I think you don't really want to rotate the bar by a certain amount each frame, but instead update its rotation at each frame with respect to the finger.
You are currently rotating the bar not considering the exact (x,y) mouse2D position of current frame, which is what you need.
This script works for me, assuming you assign it to the child of the pivot (as I assume you did from the screenshot)
public class TestRotateController : MonoBehaviour
{
//member variables
void Update() {
//[...] take the input as you did...
//else
if (Input.GetMouseButton(0)) {
//if(touchItem != null...) {
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 mousePos2D = new Vector2(mousePos.x, mousePos.y);
RotateFollowPoint(mousePos2D);
//}
}
//[else...]
}
//sets the angle of the bar to point in the direction of targetPoint2D
void RotateFollowPoint(Vector2 targetPoint2D) {
Vector2 position2D = new Vector2(transform.parent.position.x, transform.parent.position.y);
float angle = Vector2.Angle(Vector2.right, targetPoint2D - position2D);
if (targetPoint2D.y < position2D.y)
angle *= -1;
transform.parent.eulerAngles = new Vector3(0, 0, angle);
}
}
First you take the position 2D of the pivot point, then you compute the acute angle between the vector pointing from the pivot to the clicked point, which is targetPoint2D - position2D, and the Vector2.right vector (which is (1,0), so a vector pointing right), which means that the bar must be oriented to the right on its default position (when rotation on Z of the pivot = 0).
Then since Vector2.Angle gives the acute angle, set it negative if it should be more than 180°, and finally just update the angle accordingly

my character jumps too strong sometimes in unity 2d

My character's jump is working fine in a straight line collider, then I noticed that when every-time my character jumps in a curve shape collider, my jump always turns too strong abnormaly. How can I fix this? I'll provide my initial code for jump movement below.
Here is the img :
Here is jump code:
float checkgroundradius = 0.50f;
public bool isgrounded2;
public Transform grouncheckslot;
public LayerMask LM;
public float JumpPower;
public float movespeed;
Rigidbody2d RB;
void Update () {
if (isgrounded && Input.GetKeyDown(KeyCode.UpArrow))
{
isgrounded = false;
jumping = true;
myanim.SetBool("groundedanim", isgrounded);
myrb.AddForce(new Vector2(0, jumpower));
}
}
void FixedUpdate()
{
isgrounded = Physics2D.OverlapCircle(checkslot.position, groundradius, LM);
myanim.SetBool("groundedanim", isgrounded);
myanim.SetFloat("verticalspeed", myrb.velocity.y);
float move = Input.GetAxis ("Horizontal");
RB.velocity = new Vector 2 (move * movespeed, RB.velocity.y);
}
When jumping up the slope, your Physics2D.OverlapCircle intersects with the slope, thus making isgrounded=true, making you apply more force if the UpArrow is pressed.
Once solution could be to check that your character is not already moving upwards before jumping
if (isgrounded && Input.GetKeyDown(KeyCode.UpArrow) && myrb.velocity.y <= 0.0f)
this way you wont jump again if you are already heading upwards.
Maybe you could play around with a smaller groundradius and/or try moving the checkslot.position in a way that it doesnt intersect with the slope in the same manner.
For jumping people use Rigidbody2D.AddForce with Forcemode.Impulse.
Also, change
if (isgrounded && Input.GetKeyDown(KeyCode.UpArrow))
to
if (Input.GetKeyDown(KeyCode.UpArrow) && myrb.velocity.y == 0)
So you don't need to bool isgrounded
I hope it helps you :)

unity How to swipe jump motion using add force.

I have a ball standing on a platform and i have written code so that every time i swipe up the ball jumps from one platform to another depending on the force of the swipe. At the moment my platforms are just placed in position by myself and i dont have a script for their random generation. The only script i have is on the player for swiping and moving forward.
Currently im making this motion by adding force in two directions, up and forward to create the projectile motion. Its working like its supposed too, but the motion is too slow. I want it to sort of move faster. Iwe tried playing with the forces as well as the mass of the ball. They do make a difference, but I still want the ball to move some what faster.
Is adding force the best way to do this? Or would you recommend a different way?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwipeScript : MonoBehaviour {
public float maxTime;
public float minSwipeDist;
float startTime;
float endTime;
Vector3 startPos;
Vector3 endPos;
float swipeDistance;
float swipeTime;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
startTime = Time.time;
startPos = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
endTime = Time.time;
endPos = touch.position;
swipeDistance = (endPos - startPos).magnitude;
swipeTime = endTime - startTime;
if (swipeTime < maxTime && swipeDistance > minSwipeDist)
{
swipe();
}
}
}
}
public void swipe()
{
Vector2 distance = endPos - startPos;
if (Mathf.Abs(distance.y) > Mathf.Abs(distance.x))
{
Debug.Log("Swipe up detected");
jump();
}
}
private void jump()
{
Vector2 distance = endPos - startPos;
GetComponent<Rigidbody>().AddForce(new Vector3(0, Mathf.Abs(distance.y/5), Mathf.Abs(distance.y/5)));
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Cube (1)") {
Debug.Log("collision!");
GetComponent<Rigidbody>().velocity = Vector3.zero;
GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
}
}
}
I was writing my answer when I noticed #Fredrik comment: pretty much all he said was in what I wrote so I'll just skip it ! (I also do not recommend increasing Time.timeScale)
The other way you could move your ball would be using ballistic equations and setting your RigidBody to Kinematic. This way you will be able to control the ball speed through code using RigidBody.MovePosition() and still get OnCollision[...] events.
Also as a side note I do not recommend using collision.gameObject.name for collision object checking but rather tagging your cubes or even setting their layer to a specific one (but I guess this may be temporary code of yours ;) ).
Hope this helps,
Either pass ForceMode.VelocityChange as a second parameter to AddForce, or make sure you divide your vector by Time.fixedDeltaTime (which has the effect of multiplying it because Time.fixedDeltaTime will be less than 1).

Unity3d - Moving camera literally cuts FPS in half?

I'm having an issue with the cameras in Unity. When the camera moves through any means it seems to cut my FPS in half if not more. It's not really noticeable on PC, unless I'm looking at the from from 800fps to about 150fps, however on mobile it'll cut the smooth 60fps I'm getting to 20fps on a Nexus 4. It's absolutely devastating.
Here's the properties for the camera I'm using & the script HOWEVER this issue still happens without ANY of these components and a completely reset camera component:
public class ViewDrag : MonoBehaviour
{
public Vector3 hit_position = Vector3.zero;
public Vector3 current_position = Vector3.zero;
public Vector3 camera_position = Vector3.zero;
public Vector2 min_position;
public Vector2 max_position;
float z = 0.0f;
MouseHolder holder;
hider sidebarHide;
GameObject gameStructure;
// Use this for initialization
void Start()
{
gameStructure = GameObject.FindGameObjectWithTag("GameStructure");
holder = gameStructure.GetComponent<MouseHolder>();
sidebarHide = GameObject.FindGameObjectWithTag("SidebarBG").GetComponent<hider>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
hit_position = Input.mousePosition;
camera_position = transform.position;
}
if (Input.GetMouseButton(0))
{
current_position = Input.mousePosition;
LeftMouseDrag();
}
if (!sidebarHide.isHidden)
{
//GetComponent<Camera2DFollow>().enabled = true;
}
if(gameStructure.GetComponent<ExecuteMovement2>().isExecuted)
{
//GetComponent<Camera2DFollow>().enabled = true;
}
}
void LeftMouseDrag()
{
// From the Unity3D docs: "The z position is in world units from the camera." In my case I'm using the y-axis as height
// with my camera facing back down the y-axis. You can ignore this when the camera is orthograhic.
//current_position.z = hit_position.z = camera_position.y;
// Get direction of movement. (Note: Don't normalize, the magnitude of change is going to be Vector3.Distance(current_position-hit_position)
// anyways.
Vector3 direction = Camera.main.ScreenToWorldPoint(current_position) - Camera.main.ScreenToWorldPoint(hit_position);
// Invert direction to that terrain appears to move with the mouse.
direction = direction * -1;
Vector3 position = camera_position + direction;
if (position.x < max_position.x && position.x > min_position.x && position.y < max_position.y && position.y > min_position.y)
{
if (!EventSystem.current.IsPointerOverGameObject() && holder.fromSlot == null )
{
if (sidebarHide.isHidden)
{
if (!gameStructure.GetComponent<ExecuteMovement2>().isExecuted)
{
//GetComponent<Camera2DFollow>().enabled = false;
transform.position = position;
}
}
}
}
}
}
Has anyone got an idea why this happens and how I can work around it if not fix it?
Through closer inspection I think it has something to do with the Canvas being screen space.. But it's kind of needed that way. Again, any workaround?
Check comments for profiler screenshot.
Problem Solved:
In the profiler I found that Canvas.SendWillRenderCanvases() was causing huge spikes. I solved the issue completely by turning off Pixel Perfect in the Canvas. Smooth as butter now.