0
\$\begingroup\$

Suppose I have an index finger composed of 3 cubes which all contain Rigidbody which have isKinematic set to true. In a hierarchy they are the parent and children like this cube1 -> cube2 -> cube3

I want to control how my finger curls using the controller which outputs strength in range 0-1, e.g. the ArrowUp button. Put simply, if I hold the up button, all the cubes would rotate around Z for 60 degrees. And if I release the button, it would rotate back to 0 degrees. (All degrees in between 0-60 are valid when the up strength is between 0-1)

How do I rotate the finger while also making it collide with other objects? For example, you could use the finger to kick a ball.

If I don't care about the collision, I can just use transform.Rotate(0, 0, buttonUpStrength) in the Update() function and attach this script to all the cubes. But I care about collision and rigidbody.MoveRotation() is not enough because the position of each child will stay at the same absolute position when I use it. So I need to use rigidbody.MovePosition() to move the children relative to the parent also. But it's still not enough, the animation is not smooth, I want the animation to be smooth so I'm thinking that AddTorque() might be a better way out, but I don't know how to use it as isKinematic=true objects cannot be used with AddTorque().

What is a smarter, simpler way of making the finger kick a ball, without the finger being pushed back by the ball?

This is how my finger looks like, it's just a cube. enter image description here

This is my script, that I attach to all cubes, in the inspector, I set cube1's angle to be 60. The children will just copy the angle of the parent:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestJointRotation : MonoBehaviour
{
    public float angle;
    private Rigidbody rb, rbParent;
    private Vector3 originalPos;
    private Quaternion originalRot;

    void Start()
    {
        rb = GetComponent<Collider>().attachedRigidbody;
        if (transform.parent != null)
        {
            rbParent = transform.parent.GetComponent<Collider>().attachedRigidbody;
        }

        originalPos = transform.localPosition;
        originalRot = transform.localRotation;
    }

    void Update()
    {
        if (rbParent)
        {
            angle = rbParent.GetComponent<TestJointRotation>().angle;
        }

        var rotation = Quaternion.identity;
        if (rbParent) 
            rotation *= rbParent.rotation;
        rotation *= originalRot;
        rotation *= Quaternion.Euler(0, 0, Input.GetAxis("Vertical") * angle);
        rb.MoveRotation(rotation);
        if (rbParent)
            rb.MovePosition(transform.parent.TransformPoint(originalPos));
    }
}
\$\endgroup\$
0
\$\begingroup\$

I honestly think your approach is not good to solve this problem. For instance, one simple solution would be to just create a mesh, animate it in a 3d animation/modeling software and import it in Unity. You could then add colliders to the objects that compose the finger, play the animation that curls the finger and thus, kick the ball.

If you want to do this using Cubes, i guess the best way would be to create an origin point foreach cube to which its children can rotate around.

You would end up with something like this: cube1->origin1->cube2->origin2->cube3.
Now you can choose to animate the whole thing directly with Unity animation system or just attach a script that rotates the origin1/origin2 game objects. Again, i would personally choose the first approach, but it depends on what you are planning on doing.

\$\endgroup\$
  • \$\begingroup\$ My approach works for the physics but when I applied it to the real hand asset I bought assetstore.unity.com/packages/3d/characters/humanoids/…, stuff gets weird. The animation becomes jumpy compared to transform.Rotate (which is animating fine but it doesn't detect collision well). So rigidbody approach make physics works, animation sucks. While the transform approach make animation works, physics sucks. \$\endgroup\$ – off99555 Oct 3 '18 at 10:10
  • \$\begingroup\$ well then, if you want to use the rigidbody approach with the cubes hierarchy, just use Rigidboy.AddTorque(Vector3 force) and apply that to each origingameobject. Transform.Rotate doesn't work with physics because you are forcing the gameobject to rotate on every frame the game draws, which tries to override the rotation the GameObject's Rigidbody component is trying to apply on the object. I don't know how the asset you linked works, but the way you would make that work with physics is by adding forces to the bones that control the fingers of the hand in the same way you do with the cubes \$\endgroup\$ – Gabriele Vierti Oct 3 '18 at 11:25
  • \$\begingroup\$ When you say you would personally choose the first approach, do you mean the animation system? If so, do you have a resource link for how to do that simply with joints? \$\endgroup\$ – off99555 Oct 4 '18 at 8:01
  • \$\begingroup\$ No, unfortunately i don't any resources on that, but the "Joints" you are talking about are just gameobjects. Those joints were created by the artist in order to animate the mesh. In Unity's hierarchy, you can find a list of gameobjects that may seem empty, but in reality are used to position the mesh's vertices around when animating. Unity usually set everything up by itself, so all you really need to do is use them in a script. This method also enables you to use physics-based movement, since the joints are just plain gameobjects. \$\endgroup\$ – Gabriele Vierti Oct 4 '18 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.