Be the first to post for 'Ben's Bug Bashing Bonanza'!

If you’re reading this, there probably aren’t very many posts yet. But don’t worry, you can be the first! Either create a new post or just reply to this one to say ‘hi’.

Hi Ben and community!

Got to the end of this section and am keenly waiting for the next section but am preparing to venture on on my own and try and implement the features I want before releasing the demo to a few close friends and family.

My RPG is more of a WoW style than Diablo/Torchlight so I am aiming for a follow camera with mouse look and mouse steering and direct keyboard control (although I have left click to move in as well).

My issue is that my player is not sitting on the ground when playing (ie y=0). In click to move mode, y is set to 0.044 as below:

RPG Bug Click To Move Mode

. If I switch to direct control mode, y changes to -0.015 as below:

RPG Bug Direct Movement Mode

I have tried to work out why this is happening but can’t figure it out. For the most part the game behaves correctly but occasionally when I switch to direct mode, my player gets stuck in the Airborne animation state.

Any ideas?

Thanks,
Greg

Good point, we haven’t really gone back to work on direct mode yet.

This is probably because of the way the third person character detects the ground, could you lift him a few cm when you switch modes?

Hi Ben,

Thanks for the reply! I did try forcing the transform.y to be 0 on mode switch but it doesn’t seem to be sticking. On another note, I’ve left jump in my game and therefore some of the methods that were deleted in the course. Specifically in the HandleAirborneMovement method, I am unsure as to what the following line is actually doing:

groundCheckDistance = myRigidBody.velocity.y < 0 ? myOrigGroundCheckDistance : 0.01f;

My confusion is around what the ? and : are doing in this statement.

Thanks,
Greg

Ah, that’s their cheeky use of the ? operator, see https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator.

It’s called a ternary, and is like a simple if statement.

1 Like

Awesome! Thanks so much for the reply! I love how interactive and helpful you are in your courses! :grinning:

2 Likes

Thank you Greg, and you’re welcome (queue cheesy Moana tune)

Same like you, I use a Camera and Character movement like in World of Warcraft.If you want we can share our Code and maybe Improve what we got. I am not up to date with the course and didn’t worked on the project for a while, but I remember it all worked just fine.

Yeah that’d be awesome to see how you implemented it!

Actually I got a good Camera script , it works really good.

Camera Script
    [SerializeField]
    Transform target;
    [SerializeField]
    float targetHeight = 1.0f;
    [SerializeField]
    float distance = 12.0f;
    [SerializeField]
    float offsetFromWall = 0.1f;
    [SerializeField]
    float maxDistance = 20.0f;
    [SerializeField]
    float minDistance = 0.6f;
    [SerializeField]
    float xSpeed = 200.0f;
    [SerializeField]
    float ySpeed = 200.0f;
    [SerializeField]
    float yMinLimit = -80;
    [SerializeField]
    float yMaxLimit = 80;
    [SerializeField]
    float zoomRate = 40;
    [SerializeField]
    float rotationDamping = 3.0f;
    [SerializeField]
    float zoomDamping = 5.0f;
    [SerializeField]
    LayerMask collisionLayer = -1;
    [SerializeField]
    bool lockToRearOfTarget = false;
    [SerializeField]
    bool allowMouseInputX = true;
    [SerializeField]
    bool allowMouseInputY = true;

    bool playerInput = true;
    private float xDeg = 0.0f;
    private float yDeg = 0.0f;
    private float currentDistance;
    private float desiredDistance;
    private float correctedDistance;
    private bool rotateBehind = false;

    private void Start()
    {

        Vector3 angles = transform.eulerAngles;
        xDeg = angles.x;
        yDeg = angles.y;
        currentDistance = distance;
        desiredDistance = distance;
        correctedDistance = distance;

        if (lockToRearOfTarget)
            rotateBehind = true;
    }
    public void AllowPlayerInput(bool value)
    {
        playerInput = value;
    }
    private void LateUpdate()
    {
        if (!target)
            return;

        Vector3 vTargetOffset = new Vector3(0, 0, 0);


        if (GUIUtility.hotControl == 0 && playerInput)
        {
            if (Input.GetMouseButton(1))
            {
                Cursor.visible = false;
                if (allowMouseInputX)
                    xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                else
                    RotateBehindTarget();
                if (allowMouseInputY)
                    yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;

                if (!lockToRearOfTarget)
                    rotateBehind = false;
            }else
            {
                Cursor.visible = true;
            }
            if (Input.GetAxis("Vertical") != 0 || Input.GetAxis("Horizontal") != 0 || rotateBehind)
            {
                //RotateBehindTarget();
            }
        }
        yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);

        Quaternion rotation = Quaternion.Euler(yDeg, xDeg, 0);

        desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
        desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
        correctedDistance = desiredDistance;

        vTargetOffset = new Vector3(0, -targetHeight, 0);
        Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset);

        RaycastHit collisionHit;
        Vector3 trueTargetPosition = new Vector3(target.position.x, target.position.y + targetHeight, target.position.z);

        bool isCorrected = false;
        if (Physics.Linecast(trueTargetPosition, position, out collisionHit, collisionLayer))
        {
            correctedDistance = Vector3.Distance(trueTargetPosition, collisionHit.point) - offsetFromWall;
            isCorrected = true;
        }

        currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp(currentDistance, correctedDistance, Time.deltaTime * zoomDamping) : correctedDistance;

        currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);

        position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);

        transform.rotation = rotation;
        transform.position = position;
    }
   public void RotateBehindTarget()
    {
        float targetRotationAngle = target.eulerAngles.y;
        float currentRotationAngle = transform.eulerAngles.y;
        xDeg = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDamping * Time.deltaTime);

        if (targetRotationAngle == currentRotationAngle)
        {
            if (!lockToRearOfTarget)
                rotateBehind = false;
        }
        else
            rotateBehind = true;
    }

    static float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;
        return Mathf.Clamp(angle, min, max);

    }
}

And in the PlayerMovement.cs -> void ProcessDirectMovement
looks somehting like this

ProcessDirectMovement

void ProcessDirectMovement()
{
float h = Input.GetAxis(“Horizontal”);
float v = Input.GetAxis(“Vertical”);
bool jump = Input.GetKeyDown(KeyCode.Space);
Vector3 cameraForward = new Vector3(0, 0, 0);
Vector3 movement = new Vector3(0, 0, 0);

        if (Input.GetMouseButton(0) && Input.GetMouseButton(1))
        {    
            v = 1;
            cameraForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
            movement = v * cameraForward + h * Camera.main.transform.right;   
        }
        else
        {   
            cameraForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
            movement = v * this.transform.forward + h * this.transform.right;
        }
        thirdPersonCharacter.Move(movement, false, jump);
    }

this it how it looks Click

Looks awesome! I’ll give it a go when I’m back to my project (I’m taking the Blender course at the moment so I can model my own stuff!). One thing that caught my eye in that video is the tab targeting. How have you implemented that?

Thanks,
Greg

I’ll give u some hints because it is easy to archieve.
use OverlapSphere to recognize enemys
use an empty GameObject target and int index
now just increase or decrease index and an go through the OverlapSphere array and somthing like target = array[index].gameObject

also u can sort the enemy after distance or somthing

Hey I’ve finally gotten around to testing this and it works really well. One thing I want to do however is to have the camera in a specific position offset from the player on startup. I want to avoid manually moving the camera to the right position and would prefer to do it programmatically. I have tried setting the xDeg, yDeg values to their correct amount (25f and 90f in this case) but it seems to default the xDeg back to 80f for some reason and I can’t work out why!

Any suggestions?

@Greg_Boldiston So you want that the camera looks from the side to your player ? Ok, Increase yMaxLimit to 90 and add this xDeg = 90; yDeg = 25; in the Start method.

1 Like

Ah ha! Thanks for that. I have them the wrong way round for some reason and I didn’t once think to swap them over to try. Helps to have a second pair of eyes on something, so to speak!

I actually want it to start behind but at the desired y angle so I’ve just set x to 0 for now.

1 Like

Hello 69Unbalance,
Also me, I would use a camera script as WoW, and I met some problems with your code.

Where I must add this script in the camera?
In which script I have to save it ?

I have this follow config in the left menu: what i must modify exactly?

->FreeLookCameraRig
v Pivot
MainCamera

Thanks you before all.

Just put the Script on to the Main Camera, put your Player in the Target slot.
The Camera should not be a child of anything and no need for other Camera Script.

So I’ve decided to go a different route and use a weapon collision point to handle the damage instead of wrangling all these timing issues. I have:

public class DamagePoint : MonoBehaviour {

public float Damage = 0;
public bool Active = false;
public GameObject Holder;

// Use this for initialization
void Start () {

}

void OnTriggerEnter(Collider col)
{
if (Active)
{
if (col.gameObject.GetComponent () != null && col.gameObject != Holder)
col.gameObject.GetComponent ().TakeDamage (Damage);
}
}
}

This goes onto the actual weapon prefab itself. And, of course, you use the WeaponSystem class to plug in the damage value with CalculateDamage(), activate it when attacking / deactivate it when not, and so forth. I know it’s slightly cumbersome to have to set it to active and check who’s holding it (to avoid damaging yourself with your own weapon), but I still find it more agreeable than trying to match up animation timing with attack code timing. Overall, this is pretty similar to the projectile logic from earlier in the course (which I also revived with this with a RangedWeapon type).

Privacy & Terms