Home > database >  Set behaviours(script a) controlled by booleans(script b) based on Time.time (flocking system)
Set behaviours(script a) controlled by booleans(script b) based on Time.time (flocking system)

Time:07-05

I am working on a flocking system in Unity and am new to c#. I am working with 2 scripts - 1 that manages the overall flock (FlockTest) and the other that manages particle behaviour (FlockParticleBehaviour). I have followed a tutorial which has public boolean values that control seeking behaviour in FlockParticleBehaviour through FlockTest. In play mode, I can toggle these booleans to change the goal seeking behaviour. However, I want to automate this toggling based on time (To add it to an AR session). I have added an if statement to void Update() in the FlockTest and when I hit play, the seekGoal and obedient boolean boxes switch on and off but nothing happens to the particles. I have tried using an invoke method which didn't work(no errors but boxes dont switch on and off) and thought about trying a coRoutine but I am not sure this will work since I don't want to stop and start my script. I am at a loss as to how to get the particles obeying the boolean in update. Am I meant to be referencing in my particle behaviour script's flock function? Very new so would love some help if anyone knows a better way forward!

FlockTest script (contains if statement)

using System.Collections.Generic;
using UnityEngine;

public class FlockTest : MonoBehaviour
{
    public GameObject[] particles;
    public GameObject particlePrefab;
    public int particleCount = 10;
    public Vector3 range = new Vector3(5,5,5);
    public Vector3 innerLimit = new Vector3(1,1,1);

    public bool seekGoal = true;
    public bool obedient = true;
    public bool willful = false;

    [Range(0, 200)]
    public int neighbourDistance =50;

    [Range(0,2)]
    public float maxForce = 0.5f;

    [Range(0,5)]
    public float maxvelocity = 2.0f;

    

    // Start is called before the first frame update
    void Start()
    {
        int time = (int)Time.time;
        particles = new GameObject[particleCount];
        for(int i = 0; i < particleCount; i  )
        {
            
            Vector3 particlePos = new Vector3(Random.Range(-range.x, range.x), Random.Range(-range.y, range.y), Random.Range(-range.z, range.z));
            particles[i] = Instantiate(particlePrefab, this.transform.position   particlePos, Quaternion.identity) as GameObject;
            particles[i].GetComponent<FlockParticleBehaviour>().manager = this.gameObject;
        }
    }


    void Update()
    //    the toggles in the inspector are changing but nothing is happening with the particles. 
    { 
        int time = (int)Time.time;
    
        if(time == 3f) {
            seekGoal = false;
            obedient = false;
            willful = true;
        }
        
        if(time == 6f)
        {
            seekGoal = true;
            obedient = true;
            willful = false;
        }
    }

}

FlockParticleBehaviour script

using System.Collections.Generic;
using UnityEngine;

public class FlockParticleBehaviour : MonoBehaviour
{
    public GameObject manager;
    public Vector3 location = Vector3.zero;
    public Vector3 velocity;
    Vector3 goalPos = Vector3.zero;
    Vector3 currentForce; //this is a current force position. pushes particle around by adding all the other forces

    // Start is called before the first frame update
    void Start()
    {
        velocity = new Vector3(Random.Range(0.01f, 0.1f), Random.Range(0.01f, 0.1f), Random.Range(0.01f, 0.1f));
        location = new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y, this.gameObject.transform.position.z);
    }

    Vector3 seek(Vector3 target)
    {
        return(target - location);
    }

    void applyForce(Vector3 f)
    {
        Vector3 force = new Vector3(f.x, f.y, f.z);
        if(force.magnitude > manager.GetComponent<FlockTest>().maxForce)
        {
            force = force.normalized;
            force *= manager.GetComponent<FlockTest>().maxForce;
        }
        this.GetComponent<Rigidbody>().AddForce(force);

        if(this.GetComponent<Rigidbody>().velocity.magnitude > manager.GetComponent<FlockTest>().maxvelocity)
        {
            this.GetComponent<Rigidbody>().velocity = this.GetComponent<Rigidbody>().velocity.normalized;
            this.GetComponent<Rigidbody>().velocity *= manager.GetComponent<FlockTest>().maxvelocity;
        }

        Debug.DrawRay(this.transform.position, force, Color.white);

    }

    Vector3 align()
    {
        float neighbourdist = manager.GetComponent<FlockTest>().neighbourDistance;
        Vector3 sum = Vector3.zero;
        int count = 0;
        foreach (GameObject other in manager.GetComponent<FlockTest>().particles)
        {
            if(other == this.gameObject) continue;

            float d = Vector3.Distance(location, other.GetComponent<FlockParticleBehaviour>().location);

            if (d < neighbourdist) {
                sum  = other.GetComponent<FlockParticleBehaviour>().velocity;
                count  ;
            }
        }
        if (count >0)
        {
            sum /= count;
            Vector3 steer = sum - velocity;
            return steer;
        }

        return Vector3.zero;
    }


    Vector3 cohesion()
    {
        float neighbourdist = manager.GetComponent<FlockTest>().neighbourDistance;
        Vector3 sum = Vector3.zero;
        int count = 0;
        foreach (GameObject other in manager.GetComponent<FlockTest>().particles)
        {
            if(other == this.gameObject) continue;

            float d = Vector3.Distance(location, other.GetComponent<FlockParticleBehaviour>().location);
            if(d < neighbourdist)
            {
                sum  = other.GetComponent<FlockParticleBehaviour>().location;
                count  ;
            }
        }

        if (count > 0)
        {
            sum /= count;
            return seek(sum);
        }

        return Vector3.zero;
    }


    void flock()
    {
        location = this.transform.position;
        velocity = this.GetComponent<Rigidbody>().velocity;

        if(manager.GetComponent<FlockTest>().obedient && Random.Range(0,50) <=1)
        {
            Vector3 ali = align();
            Vector3 coh = cohesion();
            Vector3 gl;

            if(manager.GetComponent<FlockTest>().seekGoal)
            {
                gl = seek(goalPos);
                currentForce = gl   ali  coh;
            }
            else
            currentForce = ali   coh;

            currentForce = currentForce.normalized;
        }

        if(manager.GetComponent<FlockTest>().willful && Random.Range(0,50)<=1)
        {
            if(Random.Range(0,50)<1) //change direction
            currentForce = new Vector3(Random.Range(0.01f, 0.1f), Random.Range(0.01f, 0.1f),Random.Range(0.01f, 0.1f));
        }

        applyForce(currentForce);

    }

    // Update is called once per frame
    void Update()
    {
        flock();
        goalPos = manager.transform.position;
    }
}

CodePudding user response:

Several points:

  • it is much easier and cleaner to set your flock manager directly as FlockTest, not GameObject to avoid GetComponent calls.
  • I cannot understand what you want to achieve by calling (int)Time.time and comparing it later with 3 and 6. Time.time returns the number of seconds that passed from the start of the application. So your code in Update method of FlockTest script will not have any chance to be called after the seventh second of your game passed. So obedient will always be true and willful will always be false after the seventh second.
  • Your Random.Range(0, 50) <= 1 is quite a low chance. It will return an int value from 0 to 49, so it is only a 2% chance that your changes in FlockTest will apply to FlockParticleBehaviour instance. Is it what you wanted to get? You can try to remove this random from the if statement to make this chance 100% and check if this is an issue.

Right now it seems like the chance of changing something is too low to see it in several seconds of the game. As I've said above, after the seventh second your bool values will never change.

  • Related