コード例 #1
0
    void Update()
    {
        for (int i = 0; i < rockCount; i++)
        {
            Rock rock = allRocks[i];

            // cheesy and fps-dependent
            rock.size += (rock.targetSize - rock.size) * 3f * Time.deltaTime;

            if (rock.state == Rock.State.Conveyor)
            {
                rock.position.x += conveyorSpeed * Time.deltaTime;
                if (rock.position.x > maxConveyorX)
                {
                    rock.position.x -= ArmManager.armRowWidth + conveyorMargin * 2f;
                    rock.size        = 0f;
                }
            }
            else if (rock.state == Rock.State.Thrown)
            {
                rock.position += rock.velocity * Time.deltaTime;
                rock.velocity += Vector3.up * -gravityStrength * Time.deltaTime;

                TinCan nearestCan = TinCanManager.GetNearestCan(rock.position, false);
                if (nearestCan != null)
                {
                    if ((nearestCan.position - rock.position).sqrMagnitude < .5f * .5f)
                    {
                        TinCanManager.HitCan(nearestCan, rock.velocity);
                        rock.velocity = Random.insideUnitSphere * 3f;
                    }
                }

                if (rock.position.y < -5f)
                {
                    rock.state = Rock.State.Conveyor;
                    conveyorRocks.Add(rock);
                    rock.position = new Vector3(Random.Range(minConveyorX, maxConveyorX), 0f, 1.5f);
                    rock.size     = 0f;
                }
            }

            Matrix4x4 matrix = matrices[i];
            matrix.m03 = rock.position.x;
            matrix.m13 = rock.position.y;
            matrix.m23 = rock.position.z;

            matrix.m00 = rock.size;
            matrix.m11 = rock.size;
            matrix.m22 = rock.size;

            matrices[i] = matrix;
        }

        Graphics.DrawMeshInstanced(rockMesh, 0, rockMaterial, matrices);
    }
コード例 #2
0
ファイル: Arm.cs プロジェクト: mambotuna/DOTS-training
    void Update()
    {
        float time = Time.time + timeOffset;

        // resting position
        Vector3 idleHandTarget = transform.position + new Vector3(Mathf.Sin(time) * .35f, 1f + Mathf.Cos(time * 1.618f) * .5f, 1.5f);

        if (heldRock == null && windupTimer <= 0f)
        {
            if (intendedRock == null && reachTimer == 0f)
            {
                // we're idle - see if we can grab a rock
                Rock nearestRock = RockManager.NearestConveyorRock(transform.position - Vector3.right * .5f);
                if (nearestRock != null)
                {
                    if ((nearestRock.position - transform.position).sqrMagnitude < maxReachLength * maxReachLength)
                    {
                        // found a rock to grab!
                        // mark it as reserved so other hands don't reach for it
                        intendedRock          = nearestRock;
                        intendedRock.reserved = true;
                        lastIntendedRockSize  = intendedRock.size;
                    }
                }
            }
            else if (intendedRock == null)
            {
                // stop reaching if we've lost our target
                reachTimer -= Time.deltaTime / reachDuration;
            }

            if (intendedRock != null)
            {
                // we're reaching for a rock (but we haven't grabbed it yet)
                Vector3 delta = intendedRock.position - transform.position;
                if (delta.sqrMagnitude < maxReachLength * maxReachLength)
                {
                    // figure out where we want to put our wrist
                    // in order to grab the rock
                    Vector3 flatDelta = delta;
                    flatDelta.y = 0f;
                    flatDelta.Normalize();
                    grabHandTarget      = intendedRock.position + Vector3.up * intendedRock.size * .5f - flatDelta * intendedRock.size * .5f;
                    lastIntendedRockPos = intendedRock.position;

                    reachTimer += Time.deltaTime / reachDuration;
                    if (reachTimer >= 1f)
                    {
                        // we've arrived at the rock - pick it up
                        heldRock = intendedRock;
                        RockManager.RemoveFromConveyor(heldRock);
                        heldRock.state = Rock.State.Held;
                        // remember the rock's position in "hand space"
                        // (so we can position the rock while holding it)
                        heldRockOffset = handMatrix.inverse.MultiplyPoint3x4(heldRock.position);
                        intendedRock   = null;

                        // random minimum delay before starting the windup
                        windupTimer = Random.Range(-1f, 0f);
                        throwTimer  = 0f;
                    }
                }
                else
                {
                    // we didn't grab the rock in time - forget it
                    intendedRock.reserved = false;
                    intendedRock          = null;
                }
            }
        }
        if (heldRock != null)
        {
            // stop reaching after we've successfully grabbed a rock
            reachTimer -= Time.deltaTime / reachDuration;

            if (targetCan == null)
            {
                // find a target
                targetCan = TinCanManager.GetNearestCan(transform.position, true, targetXRange);
            }
            if (targetCan != null)
            {
                // found a target - prepare to throw
                targetCan.reserved = true;
                windupTimer       += Time.deltaTime / windupDuration;
            }
        }

        reachTimer = Mathf.Clamp01(reachTimer);

        // smoothed reach timer
        float grabT = reachTimer;

        grabT = 3f * grabT * grabT - 2f * grabT * grabT * grabT;

        // reaching overrides our idle hand position
        handTarget = Vector3.Lerp(idleHandTarget, grabHandTarget, grabT);

        if (targetCan != null)
        {
            // we've got a target, which means we're currently throwing
            if (windupTimer < 1f)
            {
                // still winding up...
                float windupT = Mathf.Clamp01(windupTimer) - Mathf.Clamp01(throwTimer * 2f);
                windupT    = 3f * windupT * windupT - 2f * windupT * windupT * windupT;
                handTarget = Vector3.Lerp(handTarget, windupHandTarget, windupT);
                Vector3 flatTargetDelta = targetCan.position - transform.position;
                flatTargetDelta.y = 0f;
                flatTargetDelta.Normalize();

                // windup position is "behind us," relative to the target position
                windupHandTarget = transform.position - flatTargetDelta * 2f + Vector3.up * (3f - windupT * 2.5f);
            }
            else
            {
                // done winding up - actual throw, plus resetting to idle
                throwTimer += Time.deltaTime / throwDuration;

                // update our aim until we release the rock
                if (heldRock != null)
                {
                    aimVector = AimAtCan(targetCan, lastIntendedRockPos);
                }

                // we start this animation in our windup position,
                // and end it by returning to our default idle pose
                Vector3 restingPos = Vector3.Lerp(windupHandTarget, handTarget, throwTimer);

                // find the hand's target position to perform the throw
                // (somewhere forward and upward from the windup position)
                Vector3 throwHandTarget = windupHandTarget + aimVector.normalized * 2.5f;

                handTarget = Vector3.LerpUnclamped(restingPos, throwHandTarget, throwCurve.Evaluate(throwTimer));

                if (throwTimer > .15f && heldRock != null)
                {
                    // release the rock
                    heldRock.reserved = false;
                    heldRock.state    = Rock.State.Thrown;
                    heldRock.velocity = aimVector;
                    heldRock          = null;
                }

                if (throwTimer >= 1f)
                {
                    // we've completed the animation - return to idle
                    windupTimer = 0f;
                    throwTimer  = 0f;
                    TinCanManager.UnreserveCanAfterDelay(targetCan, 3f);
                    targetCan = null;
                }
            }
        }

        // solve the arm IK chain first
        FABRIK.Solve(armChain, armBoneLength, transform.position, handTarget, handUp * armBendStrength);

        // figure out our current "hand vectors" from our arm orientation
        handForward = (armChain.Last(0) - armChain.Last(1)).normalized;
        handUp      = Vector3.Cross(handForward, transform.right).normalized;
        handRight   = Vector3.Cross(handUp, handForward);

        // create handspace-to-worldspace matrix
        handMatrix = Matrix4x4.TRS(armChain.Last(), Quaternion.LookRotation(handForward, handUp), Vector3.one);

        // how much are our fingers gripping?
        // (during a reach, this is based on the reach timer)
        float fingerGrabT = grabT;

        if (heldRock != null)
        {
            // move our held rock to match our new hand position
            heldRock.position   = handMatrix.MultiplyPoint3x4(heldRockOffset);
            lastIntendedRockPos = heldRock.position;

            // if we're holding a rock, we're always gripping
            fingerGrabT = 1f;
        }

        // create rendering matrices for arm bones
        UpdateMatrices(armChain, 0, armBoneThickness, handUp);
        int matrixIndex = armChain.Length - 1;

        // next:  fingers

        Vector3 handPos = armChain.Last();
        // fingers spread out during a throw
        float openPalm = throwCurve.Evaluate(throwTimer);

        for (int i = 0; i < fingerChains.Length; i++)
        {
            // find knuckle position for this finger
            Vector3 fingerPos = handPos + handRight * (fingerXOffset + i * fingerSpacing);

            // find resting position for this fingertip
            Vector3 fingerTarget = fingerPos + handForward * (.5f - .1f * fingerGrabT);

            // spooky finger wiggling while we're idle
            fingerTarget += handUp * Mathf.Sin((time + i * .2f) * 3f) * .2f * (1f - fingerGrabT);

            // if we're gripping, move this fingertip onto the surface of our rock
            Vector3 rockFingerDelta = fingerTarget - lastIntendedRockPos;
            Vector3 rockFingerPos   = lastIntendedRockPos + rockFingerDelta.normalized * (lastIntendedRockSize * .5f + fingerThicknesses[i]);
            fingerTarget = Vector3.Lerp(fingerTarget, rockFingerPos, fingerGrabT);

            // apply finger-spreading during throw animation
            fingerTarget += (handUp * .3f + handForward * .1f + handRight * (i - 1.5f) * .1f) * openPalm;

            // solve this finger's IK chain
            FABRIK.Solve(fingerChains[i], fingerBoneLengths[i], fingerPos, fingerTarget, handUp * fingerBendStrength);

            // update this finger's rendering matrices
            UpdateMatrices(fingerChains[i], matrixIndex, fingerThicknesses[i], handUp);
            matrixIndex += fingerChains[i].Length - 1;
        }

        // the thumb is pretty much the same as the fingers
        // (but pointing in a strange direction)
        Vector3 thumbPos    = handPos + handRight * thumbXOffset;
        Vector3 thumbTarget = thumbPos - handRight * .15f + handForward * (.2f + .1f * fingerGrabT) - handUp * .1f;

        thumbTarget += handRight * Mathf.Sin(time * 3f + .5f) * .1f * (1f - fingerGrabT);
        // thumb bends away from the palm, instead of "upward" like the fingers
        Vector3 thumbBendHint = (-handRight - handForward * .5f);

        Vector3 rockThumbDelta = thumbTarget - lastIntendedRockPos;
        Vector3 rockThumbPos   = lastIntendedRockPos + rockThumbDelta.normalized * (lastIntendedRockSize * .5f);

        thumbTarget = Vector3.Lerp(thumbTarget, rockThumbPos, fingerGrabT);

        FABRIK.Solve(thumbChain, thumbBoneLength, thumbPos, thumbTarget, thumbBendHint * thumbBendStrength);

        UpdateMatrices(thumbChain, matrixIndex, thumbThickness, thumbBendHint);

        // draw all of our bones
        Graphics.DrawMeshInstanced(boneMesh, 0, material, matrices);
    }