-1

I have to make my own Videogame in unity and I decided to redo the game Pacman, I am also very new to writing c# or coding in general. I am almost done with my project but the only thing I can`t finish is this script. It is for my ghosts in the game and I can´t find the reason why my ghosts are not able to walk in any free direction. Every time I start the game my ghosts are walking against walls and also do not change ways even when they could or are supposed to. The OnMouseUp() function was to test if they would change directions if I clicked on them but that didn't work as well. Thank you for your help.

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

public class Cats: MonoBehaviour
{

    public float speed = 0.3f;
    Vector2 dest;
    Vector2 destinationUpdate = Vector2.zero;

    // Start is called before the first frame update
    void Start()
    {
        dest = transform.position;
        DecideDirection();

    }

    // Update is called once per frame
    void FixedUpdate()
    {

        dest = (Vector2)transform.position + destinationUpdate;

        Vector2 dir = dest - (Vector2)transform.position;
        GetComponent<Animator>().SetFloat("DirX", dir.x);
        GetComponent<Animator>().SetFloat("DirY", dir.y);

        if (!Valid(transform.forward))
        {

            DecideDirection();


        }

        Vector2 p = Vector2.MoveTowards(transform.position, dest, speed * Time.fixedDeltaTime); 
        GetComponent<Rigidbody2D>().MovePosition(p); 

    }

    bool Valid(Vector2 dir)
    {
        Vector2 pos = transform.position;
        RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos); 
        return (hit.collider == gameObject.GetComponent<Collider2D>()); 

    }

    void DecideDirection()
    {
        bool finished = false;
        int counter = 0;

        while (!finished)
        {

            int r = Random.Range(0, 3); // 0 oben, 1 rechts, 2 unten, 3 links 

            Vector2 dir = Vector2.zero;

            switch (r)
            {
                case 0:
                    dir = Vector2.up;
                    break;
                case 1:
                    dir = Vector2.right;
                    break;
                case 2:
                    dir = Vector2.down;
                    break;
                case 3:
                    dir = Vector2.left;
                    break;

            }

            if (Valid(dir))
            {
                finished = true;
                destinationUpdate = dir * speed;
            }

            counter++;
            if (counter > 10)
            {
                finished = true;
            }
        }

    }


    private void OnMouseUp()
    {
        DecideDirection();
        Debug.Log("lalalalala");
    }


}
  • 2
    Sounds like a job for... debuggerman! – John Sep 26 '22 at 10:32
  • When is this `(hit.collider == gameObject.GetComponent())` true? – Jodrell Sep 26 '22 at 10:39
  • when you're hitting the collider of the ghost and not the collider of the wall. – Katharina Sep 26 '22 at 10:46
  • When you pass an integer value to Random.Range, the 2nd parameter is exclusive (is not included). To get the output 3 from that function, you need to use `Random.Range(0, 4)`. The declaration of that function is **public static int Range(int minInclusive, int maxExclusive);** – hijinxbassist Sep 26 '22 at 17:08

1 Answers1

0

On issue was already mentioned

int r = Random.Range(0, 3);

will only return values 0, 1 and 2 as the upper bound is exclusive.

=> You rather want

int r = Random.Range(0, 4);

in order to cover all options


Then in

bool Valid(Vector2 dir)
{
    Vector2 pos = transform.position;
    RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos); 
    return (hit.collider == gameObject.GetComponent<Collider2D>()); 
}

for some reason you make a LineCast between two fixed points, but you start with the one being away from yourself. This is extremely error prone and quite counterintuitive.

It could happen now that your raycast starts within a wall collider => it still only his yourself - or even worse, the dir is o small that you still start the cast within your own collider.

Ray/Casts do not hit the colliders they are started within by default.

I would rather use e.g.

bool Valid(Vector2 dir)
{
    RaycastHit2D hit = Physics2D.Raycast(transform.position, dir, MAXDISTANCE, LAYERMASK); 
    return (hit.collider); 
}

and set proper values for the maximum ray distance and use a layermask to heck only for walls. The ghost "looks" if it can see anything in a direction - you don't want to check if an "arbitrary" cast hits the ghost itself.

derHugo
  • 83,094
  • 9
  • 75
  • 115