Move object with hinge joint, but keep it connected to hinge - unity3d

I have multiple spheres in my mobile game that are attached to hinge joints. The spheres are able to swing and knock into each other, causing other spheres to swing. I am creating movement in the spheres by touching on a sphere and dragging it to a new location. Letting go is supposed to cause the sphere that I just moved to swing accordingly.
The issue is that I am able to move the spheres well outside of the space provided by the hinge. I never want the spheres to move anywhere that they wouldn't be able to swing using the hinge. I am able to move the spheres multiple units/meters away from their original position, when ideally I wouldn't be able to move them more than a few centimeters. The spheres should just stop moving if I hit a limit in the hinge.
Here's my code for the script that controls movement of the spheres:
GameObject selectedObject;
Vector3 screenPoint;
Vector3 offset;
void Update () {
if (Input.touchCount == 0)
{
return;
}
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began) // when screen is touched...
{
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenToWorldPoint(touch.position), Camera.main.transform.forward, out hit)) // ...cast a ray...
{
if (hit.collider.tag == "Sphere") //...and check if ray hits a sphere
{
selectedObject = hit.collider.gameObject;
screenPoint = Camera.main.WorldToScreenPoint(selectedObject.transform.position);
offset = selectedObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, screenPoint.z));
}
}
}
if (touch.phase == TouchPhase.Moved)
{
Vector3 touchPoint = new Vector3(touch.position.x, touch.position.y, screenPoint.z);
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touchPoint) + offset;
selectedObject.transform.position = touchPosition;
}
}
Any help is greatly appreciated! Let me know if I need to explain more or show a video of the issue.

I know I am a little late but you can use AddForce() and AddTorque() methods on the object you want to move but that works only if you have RigidBody on the object.

Related

Jump functionality for a 2D Top Down Unity game?

I am struggling to find an efficient way to let my player jump in a 2D Top Down world. I can see a lot of tutorials about platformer views where the camera is oriented at the side of the player, but nothing really working for a top down view like startdew Valley.
I am not using physics, so I move the character on the tilemap using a Couroutine which moves the player to the next position on grid, here it is my Update and DoMove methods:
private void Update()
{
if (!isMoving)
{
input.x = Input.GetAxisRaw("Horizontal");
input.y = Input.GetAxisRaw("Vertical");
if (input.x != 0)
input.y = 0;
if (input != Vector2.zero)
{
animator.SetFloat("Horizontal", input.x);
animator.SetFloat("Vertical", input.y);
var targetPos = transform.position + new Vector3(input.x, input.y, 0f);
// obstacle detection
Vector3Int obstaclesMapTile = obstacles.WorldToCell(targetPos - new Vector3(0, .5f, 0));
if (obstacles.GetTile(obstaclesMapTile) == null)
{
StartCoroutine(DoMove(targetPos));
}
}
animator.SetFloat("Speed", input.sqrMagnitude);
}
}
private IEnumerator DoMove(Vector3 newPos)
{
isMoving = true;
while ((newPos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
transform.position = Vector3.MoveTowards(transform.position, newPos, moveSpeed * Time.fixedDeltaTime);
yield return null;
}
transform.position = newPos;
isMoving = false;
}
Is there anybody which could give me an hint on how to add a jumping feature? ( ideally with animation support?) I am kind of running out of ideas.
Thanks in advance.
Just think of it as animation only. Since it is 2D top down, it's more about it looking like it jumps, and then if it has to go over something while in the jump animation, test for just that.
For example; if over hole and jump animation is playing, then allow movement over the whole, otherwise fall. So if the player presses the button for jump, the animation would play, and there should be some variable storing what animation the player is currently in.

Enemy does not look in upward direction when the player is at height

enemy not looking at the player standing at height my enemy does not look in the upward direction while shooting when the player is standing at the height i used these two methods but none of them making the enemy look towards the player when the player is at some height , im also adding the picture to make it clear
First method :
transform.LookAt (ThePlayer.transform.position);
Seond method:
Vector3 direction = ThePlayer.transform.position - transform.position;
direction.y = 0;
if (direction.x != 0 && direction.z != 0) {
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation
(direction), 1.5f * Time.deltaTime);
transform.eulerAngles = new Vector3 (0, transform.eulerAngles.y, 0);
Yeah on Draco18s's post, you should try moving the enemy's head with Tranform.LookAt(myplayer.trasform.position) however note that the enemy will look at the player's pivot point, so if the player's pivot point is at their feet, that is where the enemy will look.
Best of luck.

Collision with object on another layer isn't working in Unity?

I have two box colliders in my scene. I am basically manipulating one and the other is stationary and just on the default layer and it also has a rigidbody attached. The other object I am mostly rotating and for some reason it rotates right through the other object. It is on another layer but, I have checked the layer collision matrix and all of the boxes are checked so I'm not sure why the collision isn't happening. Is there a reason for this?
I am Rotating it with transform.Rotate. Neither of the colliders have the isTrigger selected. Any thoughts?
EDIT: Added this to show implementation of rigidbody.MoveRotation
private void FixedUpdate()
{
if (Input.GetKey(KeyCode.Y) && !colliding)
{
if (rigidBody == null)
{
rigidBody = gameObject.AddComponent<Rigidbody>();
rigidBody.isKinematic = true;
rigidBody.useGravity = false;
rigidBody.interpolation = RigidbodyInterpolation.Interpolate;
}
rot = Quaternion.Euler(0, .5f, 0);
rigidBody.MoveRotation(rigidBody.rotation * rot );
}
if (Input.GetKey(KeyCode.I) && !colliding)
{
if (rigidBody == null)
{
rigidBody = gameObject.AddComponent<Rigidbody>();
rigidBody.isKinematic = true;
rigidBody.useGravity = false;
rigidBody.interpolation = RigidbodyInterpolation.Interpolate;
}
rot = Quaternion.Euler(0, -.5f, 0);
rigidBody.MoveRotation(rigidBody.rotation * rot);
}
else if (colliding)
{
rigidBody.MoveRotation(rigidBody.rotation * Quaternion.Inverse(rot));
}
}
Collisions do not happen if you update the position or rotation of any object through the transform. You can receive the OnCollision events but you will not get the desire results if you rotate or move using the transform. Update your code to use the rigidbody for any changes to rotation and position in a fixedUpdate to receive these effects, aka colliding.

Get touch location on screen for perspective Camera

As the title of the question goes, I am trying to get the touch location on screen for perspective Camera.
Pretty much when I click a button my character has the ability to "teleport" or change it's location/transform to the same area of my finger with the Z axis hard coded.
Now I stress "Perspective Camera" because when the camera is Orthographic the following works fine.
if (canTeleport == true) {
if (Input.GetMouseButtonDown (0)) {
//fingerPos = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
// fingerPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); //Desktop
// transform.position = fingerPos;
// Debug.Log (transform.position);
//Needed for Mouse
//fingerPos = Input.mousePosition;
//Needed for Finger
fingerPos = Input.GetTouch(0).position;
//Oth Camera
fingerPos.z = -36.1f;
fingerPos = Camera.main.ScreenToWorldPoint (fingerPos);
//Pers Camera
// Vector3 screenPosition= new Vector3(0,0,0);
//fingerPos = GetWorldPositionOnPlane(screenPosition, -36.1f);
fingerPos.z = -36.1f;
transform.position = fingerPos;
Debug.Log (transform.position);
canTeleport = false;
}
}
But when in perspective it does not, I understand 2D and 3D space is different but only thing that should matter is the Z axis and i'm hard codding the Z axis so im not sure why it does not work.
any help offered will be appreciated.
thank you.
Update
The circle area is where I touched and as you can see my sprite went to the location on the canvas not in the game world.

buttons only react to clicks/touches when clicking/touching to the right of them

I'm making a 2D game in Unity3D for android. Right now I'm making buttons. And this buttons does not react clicks/touched properly. I've got same issue with mouse clicks and touches both. Every button has trigger boxcollider with a same size as an object. BUT buttons react only when I click on area, that is right from a button. I don't understand why is it so. What should I do? Here is my code:
if (Input.GetMouseButtonDown(0)) {
Vector3 i = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 1));
RaycastHit2D hit = Physics2D.Raycast (i, i);
if (hit.transform != null) {
if (hit.transform.tag == "button") {
hit.transform.gameObject.SetActive(false);
}
}
}
Also, I've instantiated an object on mouse click on "i" position to check does it convert screen position to world correctly, and it works fine.
the first parameter in Physics2D.Raycast is the origin and the second one is direction so you should make the raycast from your ray.origin in the direction of ray.direction
void Update () {
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (ray.origin, ray.direction, Mathf.Infinity);
if (hit) {
if(hit.collider.gameObject.tag=="button"){
//do something
}
}
}
}
Try to handle it by this way:
if (Input.GetMouseButtonDown(0)) {
Vector3 pos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Vector2 touchPos = new Vector2(pos.x, pos.y);
Collider2D hit = Physics2D.OverlapPoint(touchPos);
if (hit) {
Debug.Log(hit.transform.gameObject.name);
if (hit.transform.tag == "button") {
hit.transform.gameObject.SetActive(false);
}
}
}