EDIT: see post #17
EDIT/Update: see post #14
we’re doing a project about big o notation in my class. we have to teach about big o notation in some kind of media with music or sound in the background. a lot of people did powerpoints, but the professor showed one guy who actually did a video which was of a pretty decent quality. it’s a group project, and i volunteered to write a video game in unity for it. so far it looks good, and i know what i want to do.
there are two things that i’m not sure how to do, though. i want the enemy objects to patrol an area - nothing complicated, no following the player - and i want there to be platforms that move. it’s the autonomy of the object i’m not sure how to do. can anyone explain how to do this or direct me to a tutorial etc. for it? of course i’m looking at stuff on google … i might find something but if someone can just describe how to do it that would be helpful.
okay, i’m trying to get the big O to shoot little green e’s but running into some issues:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BigO : MonoBehaviour {
[HideInInspector] public bool facingRight = true;
[HideInInspector] public bool jump = false;
public float moveForce = 365f;
public float maxSpeed = 5f;
public float jumpForce = 1000f;
public Transform groundCheck;
public GameObject ebullet;
private bool grounded = false;
private Animator anim;
private Rigidbody2D rb2d;
public GameObject bullet;
private Rigidbody2D rb2d_e;
// Use this for initialization
void Awake()
{
rb2d = GetComponent<Rigidbody2D>();
rbd2d_e = bullet.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if (Input.GetKeyDown(KeyCode.UpArrow) && grounded)
{
jump = true;
}
//if y value is too low, show lose game screen
//if space pressed, shoot e's
if (Input.GetKeyDown(KeyCode.Space))
{
bullet = Instantiate(ebullet, transform);
bullet.transform.position = transform.position += new Vector3(4, 2, 0);
if (facingRight)
bullet.rb2d_e.AddForce();
else if (!facingRight)
bullet.rb2d_e.AddForce();
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
if (h * rb2d.velocity.x < maxSpeed)
rb2d.AddForce(Vector2.right * h * moveForce);
if (Mathf.Abs(rb2d.velocity.x) > maxSpeed)
rb2d.velocity = new Vector2(Mathf.Sign(rb2d.velocity.x) * maxSpeed, rb2d.velocity.y);
if (h > 0 && !facingRight)
Flip();
else if (h < 0 && facingRight)
Flip();
if (jump)
{
rb2d.AddForce(new Vector2(0f, jumpForce));
jump = false;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
having issues with lines 29, 48, and 50.
edit: oops, misspelled rb2d_e, so only lines 48 and 50
I assume there is no Rigidbody component on the “bullet”.
You’ll need to GetComponent after you’ve instantiated it into the scene.
1 Like
EDIT: okay, i got the add force right because the bullets shoot out correctly. however, the big O (the object the script is attached to) still “teleports” when i shoot. need to figure that out.
it’s this line 
bullet.transform.position = transform.position += new Vector3(4, 2, 0);
remove the second = ^^
+= adds the vector to your transforms(BigOs) position as well as setting the bullets position to it’s intended value
1 Like
Back go your original questiom for patrolling enemies is this 2d or 3d? How do you want them to patrol? (E.g. walking back and forth always).
For the moving platform you can use animation curves to define how the platform moves, add two empty gameobjects one for the platform to move from, one for it to move to. Then have a float that rises by Time.deltaTime * yourSpeed, pass this to your animation curve, pass that to a Vector3.Lerp that will have the two empty gameobjects positions. Anytime the number goes over 1 take 1 off of it, then you will have a reusable moving platform.
1 Like
Big-O is about speed. The way to show it is using two algorithms wth different ones. Switch between them and show the massive difference.
One easy one is “compare everything to everything else in a list.” That’s n^2. But for certain problems, it can be faster. For example, moving balls can always draw a line to ball with the next larger x-coord (so you always see a left-to-right big zaggy line.) A simple nested n^2 loop can do that. Or, sort them by x and draw a line to the next ball. That’s n*log(n). Hardy seems better, as you add more balls the second is clearly faster.
Or, gameObject.Find is a loop through all gameObjects. There are many examples here of someone using it in a loop or even a nested loop, getting O(n^3) As the size grows, you see a big slow-down. Replacing the go.find is no change at small sizes, but a big change when you have many.
1 Like
You want to be printing or recording the time it takes to execute the algorithms, and then comparing those values as you scale up the order of operations. Youll end up with essentially a load of numbers that you can average to get an average algorthm efficiency formula, but you will also be able to use the incremental data to plot things like exponential computation as the curve goes up.
Sounds very similar to the assignment I did in my first year back at uni for algorithm efficiency.
1 Like
Exactly. Numbers and formulas are for tweaks where you might get a 2% increase. Big-O is about massive performance swings, as size increases (both things are important.)
Ex: for 100 objects A and B run about the same; for 1000 objects method A seems a little slower; for 10,000 objects – B still runs but A is at a crawl. That extra loop finally killed it. It’s a tricky subject. I have a natural advantage, being one myself 
2 Likes
EDIT: nevermind, needed oncollisionenter2d
EDIT: okay, here is my crappy code. there are probably a few things wrong with it, mainly the update function:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AutonomousMovement : MonoBehaviour {
public Transform[] points;
private int destPoint = 0;
public Vector3 initial;
void Start()
{
GotoNextPoint();
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Length == 0)
return;
// Set the agent to go to the currently selected destination.
Vector2.MoveTowards(initial, points[destPoint].position, 10f * Time.deltaTime);
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
initial = points[destPoint].position;
destPoint = (destPoint + 1) % points.Length;
}
void Update()
{
// Choose the next destination point when the agent gets
// close to the current one.
if ((transform.position.x <= points[destPoint].position.x + new Vector2(1, 1).x && transform.position.y <= points[destPoint].position.y + new Vector2(1, 1).y) ||
(transform.position.x >= points[destPoint].position.x - new Vector2(1, 1).x && transform.position.y >= points[destPoint].position.y - new Vector2(1, 1).y))
GotoNextPoint();
}
}
need help getting this “patrol” script running. i’m using it for my enemies and for moving platforms.
For one thing, you never assign the result of your MoveTowards…
1 Like
now i got some movement (set transform.position to vector2.movetowards). basically i have two quivering game objects at both of the two empty transforms i assigned. so i’m still stuck, though i think this behavior is an improvement.
edit: okay, seeing some of what’s wrong with this …i’ll post the updated code if i get this working, but still would welcome help
where i am currently:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AutonomousMovement : MonoBehaviour {
public Transform[] points;
private int destPoint = 0;
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Length == 0)
return;
destPoint = (destPoint + 1) % points.Length;
}
void Update()
{
transform.position = Vector2.MoveTowards(transform.position, points[destPoint].position, 2f * Time.deltaTime);
// Choose the next destination point when the agent gets
// close to the current one.
if (transform.position.x == points[destPoint].position.x)
{
GotoNextPoint();
}
}
}
edit2: now it works! yay and i did it myself mostly
this code controls my player object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class BigO : MonoBehaviour {
[HideInInspector] public bool facingRight = true;
[HideInInspector] public bool jump = false;
public float moveForce = 365f;
public float maxSpeed = 5f;
public float jumpForce = 500f;
public Transform groundCheck;
public GameObject ebullet;
public float bulletForce = 1000f;
private bool grounded = false;
private Animator anim;
private Rigidbody2D rb2d;
public GameObject bullet;
private Rigidbody2D rb2d_e;
// Use this for initialization
void Awake()
{
rb2d = GetComponent<Rigidbody2D>();
//rb2d_e = bullet.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if (Input.GetKeyDown(KeyCode.UpArrow) && grounded)
{
jump = true;
}
//if y value is too low, show lose game screen
if (transform.position.y <= -5)
{
SceneManager.LoadScene("LoseScreen", LoadSceneMode.Single);
}
//if space pressed, shoot e's
if (Input.GetKeyDown(KeyCode.Space))
{
bullet = Instantiate(ebullet, transform);
bullet.transform.position = transform.position + new Vector3(1, 1, 0);
rb2d_e = bullet.GetComponent<Rigidbody2D>();
if (facingRight)
rb2d_e.AddForce(bullet.transform.right * bulletForce);
else if (!facingRight)
rb2d_e.AddForce(-bullet.transform.right * bulletForce);
}
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
if (h * rb2d.velocity.x < maxSpeed)
rb2d.AddForce(Vector2.right * h * moveForce);
if (Mathf.Abs(rb2d.velocity.x) > maxSpeed)
rb2d.velocity = new Vector2(Mathf.Sign(rb2d.velocity.x) * maxSpeed, rb2d.velocity.y);
if (h > 0 && !facingRight)
Flip();
else if (h < 0 && facingRight)
Flip();
if (jump)
{
rb2d.AddForce(new Vector2(0f, jumpForce));
jump = false;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "enemy")
{
//play audio
Destroy(gameObject);
SceneManager.LoadScene("LoseScreen", LoadSceneMode.Single);
}
}
}
it’s just code modified from a unity tutorial. i’m able to jump in midair infinitely, which i do not want. how to fix this?
this is basically a linecasting issue but still i set the platform you stand on to layer Ground … and i dragged the platform into the GroundCheck transform.
edit: i tried this - RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up, 0.01f);
and putting hit.collider != null instead of grounded, but it still allows infinite jumps
Firstly I would just make a public LayerMask so that it can be modified and debugged in the inspector. I have never used LineCast so cannot comment on its use but I would say more often than not a Raycast would be the most common option. Note that you can debug Raycasts in the editor by using Debug.DrawRay so you can see exactly whats going on.
1 Like
works now! not exactly sure what i did, but something to do with layer masks. thanks!
okay, none of my sounds (besides the music) are playing. i set up an audio source on each of the objects with scripted sounds. there are three sounds that are supposed to play on collision. so i just put a public audio clip, set up the reference, and told it to play one shot. that didn’t work, so i tried this:
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "enemy")
{
audio4.clip = dead1;
audio4.Play();
Destroy(gameObject);
SceneManager.LoadScene("LoseScreen", LoadSceneMode.Single);
}
}
[/code[
audio4 is an audio source and dead1 is an audio clip. the music continues playing in the background, but none of the sounds play on collision.
i used a coroutine because i figured i couldn’t hear the sound due to the game transitioning to the lose screen or the next level. so i tried this:
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "enemy")
{
audio4.PlayOneShot(dead1);
StartCoroutine(Wait());
Destroy(gameObject);
SceneManager.LoadScene("LoseScreen", LoadSceneMode.Single);
}
}
IEnumerator Wait()
{
yield return new WaitForSeconds(dead1.length);
}
still doesn’t play the sfx…
Did you try to move the Destroy(gameObject) and LoadScene to after the WaitForSeconds? 
1 Like