1 (edited by Steviebops 2014-06-25 15:12:18)

Topic: Z - axis movement

I'm starting to look at coding for z-axis movement (3d Arena), I'll be starting with the basic 4-direction, then hopefully expanding it into a full 8-way system.

Any code or help would be appreciated.

The first task is to find a way to mix the horizontal and vertical axes together. Currently Vertical is for jump and crouch. my idea is similar to Soul Calibur, where movement takes priority, and you can only jump or crouch with the block held.
The jump = input + block is actually rather easy.

It's the direction input that's the first tricky part.

Share

Thumbs up Thumbs down

2 (edited by Steviebops 2014-06-26 21:09:59)

Re: Z - axis movement

The physics code uses this

public void Move(int mirror, float direction)
    {
        if (!IsGrounded()) return;
        moveDirection = direction;
        if (mirror == 1)
        {
            horizontalForce = myControlsScript.myInfo.physics.moveForwardSpeed * direction;
        }
        else
        {
            horizontalForce = myControlsScript.myInfo.physics.moveBackSpeed * direction;
        }
    }

Which is called in the ControlsScript by

{
                        inputRef.engineRelatedButton = mirror == 1 ? ButtonPress.Back : ButtonPress.Foward;
                        if (inputRef.heldDown == 0 && testMoveExecution(inputRef.engineRelatedButton, false)) return;
                        inputRef.heldDown += Time.deltaTime;
                        if (currentState == PossibleStates.Stand && !isBlocking && !stunned && !blockStunned)
                            if (currentMove == null) myPhysicsScript.Move(-mirror, inputController.GetAxisRaw(inputRef));
                    }

                    if (inputController.GetAxisRaw(inputRef) < 0)
                    {
                        inputRef.engineRelatedButton = mirror == 1 ? ButtonPress.Foward : ButtonPress.Back;
                        if (inputRef.heldDown == 0 && testMoveExecution(inputRef.engineRelatedButton, false)) return;
                        inputRef.heldDown += Time.deltaTime;
                        if (currentState == PossibleStates.Stand && !isBlocking && !stunned && !blockStunned)
                            if (currentMove == null) myPhysicsScript.Move(mirror, inputController.GetAxisRaw(inputRef));
                    }

and finally, applied back PhysicsScript by

 if (horizontalForce != 0 && !isTakingOff)
            {
                if (horizontalForce > 0)
                {
                    horizontalForce -= appliedFriction * Time.deltaTime;
                    horizontalForce = Mathf.Max(0, horizontalForce);
                }
                else if (horizontalForce < 0)
                {
                    horizontalForce += appliedFriction * Time.deltaTime;
                    horizontalForce = Mathf.Min(0, horizontalForce);
                }


                transform.Translate(horizontalForce * Time.deltaTime, 0, 0);
            }

I just can't figure out how to patch in the second axis to this system.

I know the final z-axis force will be use in Translate, it's just using the vertical axis to calculate it and pass it to the move method that's got me stuck.

Share

Thumbs up +1 Thumbs down

Re: Z - axis movement

So far Ive implemented a simple side movement and changed to collision spheres to align with their parent parts in 3d.

My next step will be to have the rotation sorted so the chars  face each other. Similarly to the head look feature, you will probably want to be able to turn that off during moves, so the move can actually be evaded, and not track like a player seeking missile wink


Dashing is another feature to think about. Ill be using short dashes, rather then 8-way run, so making the dash a move in itself might work for that.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Steviebops wrote:

I'm starting to look at coding for z-axis movement (3d Arena), I'll be starting with the basic 4-direction, then hopefully expanding it into a full 8-way system.

Any code or help would be appreciated.

The first task is to find a way to mix the horizontal and vertical axes together. Currently Vertical is for jump and crouch. my idea is similar to Soul Calibur, where movement takes priority, and you can only jump or crouch with the block held.
The jump = input + block is actually rather easy.

It's the direction input that's the first tricky part.

Glad to hear this.  This is the same setup I'd like to use. 

Working on using a 4 way dash initially before adding an 8 way run/walk mechanic is smart too.  How do you make separate quadrants for hit detection (front/left/right/back)?

Share

Thumbs up Thumbs down

5 (edited by Steviebops 2014-07-01 14:59:55)

Re: Z - axis movement

At the moment, Im using the standard hit detection, so Im not there yet.

I had used a simple system before, on an older project

public void getRotation()
    {
        Vector3 relativePoint = transform.InverseTransformPoint(opponentTarget.position);
        if (relativePoint.z < 0.0f)
        {
            facingFront = false;
            //  Debug.Log("Facing behind" + relativePoint.z);
        }
        else if (relativePoint.z > 0.0f)
        {
            facingFront = true;
            // Debug.Log("Facing ahead" + relativePoint.z);
        }

    }

Which might be a good starting point, but is still fairly simple, as I only used it to test whether an opponent is being hit form the left or right side, and snapping the head accordingly.
There's actually something quite similar in the ControlsScript, the testCharacterRotation method.

My thinking here was to extend this too look at the directions of the player rather than adding more hit detection tests.

Have you worked on quadrants? I'd be interested in hearing more.

Share

Thumbs up +1 Thumbs down

Re: Z - axis movement

Also, here's the old rotation code from that project, if it's of any use.

 void Rotating(CharacterController controller)
    {
        float damping = 6.0f;    //to control the rotation 
        bool smooth = true;

        Transform _myTransform = controller.transform;

        if (opponentTarget)
        {
            if (smooth)
            {
                //Look at and dampen the rotation
                Quaternion rotation = Quaternion.LookRotation(opponentTarget.position - _myTransform.position);
                _myTransform.rotation = Quaternion.Slerp(_myTransform.rotation, rotation, Time.deltaTime * damping);
            }
            else
            { //Just look at
                _myTransform.rotation = Quaternion.FromToRotation(-Vector3.forward,
                    (new Vector3(opponentTarget.position.x, opponentTarget.position.y, opponentTarget.position.z)
                    - _myTransform.position).normalized);

                float distance = Vector3.Distance(opponentTarget.position, _myTransform.position);
            }
        }
    }

Share

Thumbs up +1 Thumbs down

Re: Z - axis movement

Sadly, I'm of virtually no use when it comes to coding.  I'm an artist who's trying to get a proof of concept together before presenting it to a family member/investor so that I can hire a coder.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Ive got a simple implentation, the characters rotate to face, and you can circle around each other. More to come later.

Share

Thumbs up +2 Thumbs down

Re: Z - axis movement

In order to test eh hit quadrant thing, here's the code I used.

   private void TestAlignment()
    {
        if (gameObject.name == "Player1")
        {
            Vector3 forward = character.transform.TransformDirection(Vector3.forward);
            Vector3 sides = character.transform.TransformDirection(Vector3.left);
            Vector3 n = character.transform.TransformDirection(Vector3.up);
            Vector3 toOther = opponent.transform.position - character.transform.position;
            // Vector3 heading = new Vector3(Vector3.Dot(sides, toOther), 0, Vector3.Dot(forward, toOther));


            // angle in [0,180]
            float angle = Vector3.Angle(forward, toOther);
            float sign = Mathf.Sign(Vector3.Dot(n, Vector3.Cross(forward, toOther)));

            // angle in [-179,180]
            float signed_angle = angle * sign;

            // angle in [0,360]
            float angle360 = ((signed_angle) + 360) % 360;

            print(angle360);

            if (angle360 > 315 || angle360 < 45)
            {
                front = true;
            }
            else { front = false; }

            if (angle360 < 225 && angle360 > 135)
            {
                rear = true;
            }
            else { rear = false; }


            if (angle360 > 225 && angle360 < 315)
            {
                left = true; 
            }
            else { left = false; }

            if (angle360 < 135 && angle360 > 45)
            {
                right = true;
            }
            else { right = false; }

            if (front == true) { print("The other transform is ahead!"); }
            if (rear == true) { print("The other transform is behind!"); }
            if (left == true) { print("The other transform is to my left!"); }
            if (right == true) { print("The other transform is to my right!"); }
        }
    }

It seems to be ok so far. But if anyone wants to have a look, see if it has room for improvement. Next step will be to link that  to the hit detection system, so we can trigger different animations based on direction, as well as see how push/pull forces might need to be changed.

Share

Thumbs up +2 Thumbs down

Re: Z - axis movement

Bit of a bug, it turns out the movement isn't working right. You can move in all directions, but the existing system sets speed and applies forces based on the 'mirror' variable.

I need to figure out how to fix movement so direction isn't set as the World space -x axis, but is set relative between the characters.
For instance, forward is towards the opponent, not the left/right of the screen.

This is going to take a while, as I'm not yet sure how to make the change. It looks like the knock-on changes are going to be tough to deal with.

Share

Thumbs up Thumbs down

11 (edited by Steviebops 2014-07-23 14:28:26)

Re: Z - axis movement

I've got a workaround for the movement. It looks a little weird with the static camera, but eventually the camera will rotate to keep the players side-on.


I'm working on the physics forces, which is tricky, as they were designed for 2.5d. once you move off the z-axis, knocking the character directly back across the universal axis doesn't look right.

I'm interested in a solution where the forces are applied based on the player object's local axis, not the world axis.

Character.transform.Translate doesn't seem to work in the Physics script though.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Steviebops,

Steviebops wrote:

I'm starting to look at coding for z-axis movement (3d Arena), I'll be starting with the basic 4-direction, then hopefully expanding it into a full 8-way system.

How have you been going with this?
I noticed you haven't posted anything in this thread since for about two weeks: (2014-07-23 22:28:26)

Steviebops wrote:

I've got a workaround for the movement. It looks a little weird with the static camera, but eventually the camera will rotate to keep the players side-on.

I just saw your response to the thread: Season 3 Polls: Major Updates

Steviebops wrote:

I've decided to implement my own 3d-movement system in the mean time. So far Ive implemented a simple side movement and changed to collision spheres to align with their parent parts in 3d.

Once I've sorted out a rotations system so the players face each other, Ill share what I have.

I have a thread to discuss it, if anyone is interested.

I am very interested, not sure why I wasn't getting email notifications as I had subscribed to the poll thread....I just got an email today which is why I came to the thread and then saw your post and came here..... wink

I'll try and have a go at integrating your code in a project myself and see how I go. I'll report back once I have tried it out.

Thanks for taking the initiative and coming up with a solution.

Share

Thumbs up Thumbs down

Re: Z - axis movement

I've got some of the basics going. The characters can step around each other. I had planned on showing where I was once I got the camera sorted.
In order to work the camera needs to track the players, and rotate, rather than just translate.

The code itself would probably need a lot of cleaning too, I've kind of hacked in the features I wanted.

Share

Thumbs up Thumbs down

Re: Z - axis movement

I was hoping to use the code from an old project for the camera.
I took the Start and LateUpdate from this old class, and merged it into UFE's camera script

using UnityEngine;
using System.Collections;

public class NewCam : MonoBehaviour
{
    Transform P1Trans;
    Transform P2Trans;
    public float distScale = 3.0f;

    void Start()
    {
        GameObject P1 = GameObject.FindGameObjectWithTag("Fighter1");
        GameObject P2 = GameObject.FindGameObjectWithTag("Fighter2");

        Transform[] allChildren1 = P1.GetComponentsInChildren<Transform>();
        Transform[] allChildren2 = P2.GetComponentsInChildren<Transform>();

        foreach (Transform child1 in allChildren1)
        {
            if (child1.name == "camPointer")
            {
                P1Trans = child1;
            }
        }
        foreach (Transform child2 in allChildren2)
        {
            if (child2.name == "camPointer")
            {
                P2Trans = child2;
            }
        }
    }

    void LateUpdate()
    {
        Physics.IgnoreLayerCollision(8, 9, true);
        Vector3 target = (P1Trans.position - P2Trans.position);
        Vector3 Perpendicular = Vector3.Cross(target, Vector3.up);
        Vector3 midPoint = (P1Trans.position + P2Trans.position) * 0.5f;
        float dist = Vector3.Distance(P1Trans.position, P2Trans.position);

        if (rigidbody.position != midPoint + Perpendicular.normalized * dist * distScale)
        {
            rigidbody.velocity = (midPoint + Perpendicular.normalized * dist * distScale) - rigidbody.position;
        }
        else
        {
            rigidbody.velocity = new Vector3(0, 0, 0);
        }
        camera.transform.LookAt(midPoint);
    }


}

I'm having trouble with the camPointer objects, which are empty objects added to the character prefabs, and set at head height. These are what I used before to set the camera height.

 Vector3 target = (P1Trans.position - P2Trans.position);

is throwing the error "Object reference not set to an instance of an object". I'm not sure why, but UFE seems to struggle with this. I used a rigidbody on the camera previously, because as you will have walls in a 3d arena fighter, I needed the camera to stay inside them.


If anyone can help, we can hopefully move on to the next issue.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Can you confirm that both P1Trans and P2Trans are assigning correctly in Start()?  I'd put a quick check after the last foreach loop.  Something like:

if (P1Trans == null || P2Trans == null) Debug.Log("Player Transform(s) not assigned!");

I'm suspecting you're looking for them before they're created, but that's just a hunch looking at your code without testing...

Share

Thumbs up +1 Thumbs down

Re: Z - axis movement

Yeah, that seems to be the case. Now to fix it. Ill crack into it tomorrow.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Hmm, Im having some difficulty. I'm not sure how to find the campointer empty I put on each player prefab. In UFE it would be a child of the (clone) objects under Game.Player1, but I can't seem to access it.

Does anyone know how?

Share

Thumbs up Thumbs down

18 (edited by YumChaGames 2014-08-07 23:27:59)

Re: Z - axis movement

How have you put the cam pointer empty in each player prefab?  After instantiation, or is it in the prefab already?
And while running the game, can you confirm the empty is actually a child of the player transform?

EDIT: just read your other post about it wink.

OK, so it's attached (a child?) of the head transform.

It's probably not the best method, but have you tried a direct path like in this example?

http://docs.unity3d.com/ScriptReference … .Find.html

Share

Thumbs up Thumbs down

Re: Z - axis movement

I don't think the direct path would work, as each character would have a different one.

If you run UFE, you see the structure, Game/Player1/prefab instance.

That prefab instance is a clone of your character prefab, and it's in that the campointer is. I tried searching for the campointer as a child of Player1, and even Game, but I can't seem to get at them.

Share

Thumbs up Thumbs down

Re: Z - axis movement

OK, it's a bit of a hack, but what I'd do is just manually assign the empty on the prefab.

So, in a script on the prefab create a variable

public Transform childEmpty

.  Then in Unity, drag the prefab to the scene, drag the empty child into the childEmpty variable on the parent script, then re-save the prefab.  When you want to access the empty, get to it via the parent's script public variable.

It does mean you'll need to do this for each character, but without seeing why you're not able to search for the empty I can't think of another way to get it working.

Share

Thumbs up +1 Thumbs down

21 (edited by Steviebops 2014-08-08 15:19:20)

Re: Z - axis movement

Seems to have the same problem, you can get Game and Player, and that's it, I can't get the scripts or objects attached to the prefab instances themselves.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Not even with something like:

CustomScript customScript = Player.gameObject.GetComponent<CustomScript>();

If that's not even working, than I have no idea…

So I understand clearly, what would accessing these empties in each player allow you to do?  Hopefully there's another way to achieve what you want without needing to access children of player prefabs.

Share

Thumbs up Thumbs down

Re: Z - axis movement

I've got the campointer issue solved. Now I'm working on smoothing out the camera. I think the issue is the bounds for the stage. If you use the square bounds already implemented, the camera gets very jittery around corners, as it's basically following the fighters.

The camera uses physics, but the characters don't.

My current thinking is finding a way to change the bounds of the level to a ring, by creating a procedural circle from the centre of the level, based on a public radius variable, which replaces the two stage boundary ones.

I'm not sure how to make that circle, and use it as a clamp though, so any help, as always, is appreciated.

Share

Thumbs up Thumbs down

Re: Z - axis movement

I am using this code

 float dst = Vector3.Distance(stageCentre, transform.position);
        if (dst > radius)
        {
            Vector3 vect = stageCentre - transform.position;
            vect = vect.normalized;
            vect *= (dst - radius);
            transform.position += vect;
        }

to constrain the player transform. I use Vector3.zero as the centre of the level.

Unfortunately, I am still seeing the jerky/jittering movement on the camera at certain angles.

I may remove the physics from the camera entirely, and just use transform as before. My rationale for the physics on the cam was to create a cylinder inside the level, that would stop the camera from moving outside the walls, while moving smoothly along the inside of the cylinder.

I think I'll use the same code as the player limit instead, with a larger circle as a bound.

I'll update with the results.

Share

Thumbs up Thumbs down

Re: Z - axis movement

Have you looked at the camera scripts from Unity tutorials?  They're very smooth, and would easily be doable for UFE.

I'm curious, what was the solution to the campointer issue?

Share

Thumbs up Thumbs down