2D SPACE ADVENTURE SHOOTER : Need help from SCRIPTING GODS. Please help me.

Ok guys I’m making a top-down space shooter adventure, I got the basic movement, bullets and enemies.

The player will be controlling the ship and the camera is scripted to the ship so it follows where ever it moves.

Part where I need help:

  • Enemies collision
  • - Power-ups system [REALLY REALLY NEED HELP) :frowning:*
  • - Bullets move slow while the ship is moving forward… I can’t seem to make the velocity of the ship + the bullet work…*
  • - Enemy spawn, so far I got a individual spawn, I probably need the enemies to spawn from the camera…because this game is an open world adventure… but I need different waves of enemies spawning.*
  • [/B]*
  • About the enemies collision; the enemies are suppose to follow the player everywhere it goes and it does. The problem is that Unity’s physics engine doesn’t separate the enemies, that over time they will be on the same spot… and could be all killed by 1 bullet. How do I make it so that the enemies separates from each other and have space between them while still following the player?*
  • About the power-ups… this is the real trouble for me, I got no idea how to tackle this.*
  • Basically the power will gain EXP after killing enemies, [I could probably code this]*
  • Once the player have enough EXP, they could unlock any power-ups at any order depending on which power-up they want.*
  • Then the ship will release 4 random power-ups that the player can pick-up… it will maintain 4 power-ups at all time with a timer.*
  • The power-up will stay within the camera (I could probably add a empty gameobject with collision on the corner of the camera).*
  • Player AI code (movement/enemies follow/bullet/camera)*
  • ```*
  • *using UnityEngine;
    using System.Collections;

public class AIscript : MonoBehaviour {
//game objects (variables which point to game objects)
private GameObject objPlayer;
private GameObject objCamera;

public Rigidbody rocketPrefab;
public Transform barrelEnd;

private Variables ptrScriptVariable;

//input variables (variables used to process and handle input)
private Vector3 inputRotation;
private Vector3 inputMovement;

//identity variables (variables specific to the game object)
public float moveSpeed = 100f;
private float enemySpeedUp = 5.0f;
private bool thisIsPlayer;


// calculation variables (variables used for calculation)
private Vector3 tempVector;
private Vector3 tempVector2;
private float tempSpeed;


// Use this for initialization
void Start () {
	objPlayer = (GameObject) GameObject.FindWithTag ("Player");
	objCamera = (GameObject) GameObject.FindWithTag ("MainCamera");
	if (gameObject.tag == "Player") { thisIsPlayer = true; }
	ptrScriptVariable = (Variables) objPlayer.GetComponent( typeof(Variables) );
}

// Update is called once per frame
void Update () {
	FindInput();
	ProcessMovement();
	if (thisIsPlayer == true)
	{
		HandleCamera();
	}
}

void FindInput ()
{
	if (thisIsPlayer == true)
	{
		FindPlayerInput();
	} 
		else 
	{	
		if(Time.time >= enemySpeedUp)
	{
	// Add 100 to the moveSpeed...
		moveSpeed += 100f;
	// make it wait another  5sec...
		enemySpeedUp += 5.0f;
		print (this.moveSpeed);
		}
		FindAIinput();
	}
}
	void FindPlayerInput ()
	{
		// find vector to move
		inputMovement = new Vector3( Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical") );

		// find vector to the mouse
		tempVector2 = new Vector3(Screen.width * 0.5f,0,Screen.height * 0.5f); // the position of the middle of the screen
		tempVector = Input.mousePosition; // find the position of the moue on screen
		tempVector.z = tempVector.y; // input mouse position gives us 2D coordinates, I am moving the Y coordinate to the Z coorindate in temp Vector and setting the Y coordinate to 0, so that the Vector will read the input along the X (left and right of screen) and Z (up and down screen) axis, and not the X and Y (in and out of screen) axis
		tempVector.y = 0;
		inputRotation = tempVector - tempVector2; // the direction we want face/aim/shoot is from the middle of the screen to where the mouse is pointing
	
		if(Input.GetButtonDown("Fire1"))
        {
            Rigidbody rocketInstance;
			tempVector = Quaternion.AngleAxis(0.1f, Vector3.up) * inputRotation;
			tempVector = (transform.position + (tempVector.normalized * 0.8f));
			tempSpeed = 20.0f + rigidbody.velocity.magnitude;
            rocketInstance = Instantiate(rocketPrefab,barrelEnd.position,Quaternion.LookRotation(inputRotation)/*barrelEnd.rotation*/) as Rigidbody;
            rocketInstance.AddForce(barrelEnd.forward * tempSpeed);
			rocketPrefab.transform.forward = transform.forward;
	
        }
	}


void FindAIinput ()
	{
	inputMovement = objPlayer.transform.position - transform.position;
	inputRotation = inputMovement; // face the direction we are moving
	}
void ProcessMovement()
{
	tempVector = rigidbody.GetPointVelocity(transform.position) * Time.deltaTime * 1000;
	rigidbody.AddForce (-tempVector.x, -tempVector.y, -tempVector.z);

	rigidbody.AddForce (inputMovement.normalized * moveSpeed * Time.deltaTime);
	transform.rotation = Quaternion.LookRotation(inputRotation);
	transform.eulerAngles = new Vector3(0,transform.eulerAngles.y + 180,0);
	transform.position = new Vector3(transform.position.x,0,transform.position.z);
}
void HandleCamera()
{
	objCamera.transform.position = new Vector3(transform.position.x,5,transform.position.z);
	objCamera.transform.eulerAngles = new Vector3(90,0,0);
}
void OnTriggerEnter(Collider whatHitMe)
{
	if(whatHitMe.gameObject.tag=="Player")
	{
		print("Player Destroyed");
		Destroy (whatHitMe.gameObject);
		Destroy (this.gameObject);
		
	}
}

// void removeMe ()
//{
//Destroy(gameObject);
//}
// void OnCollisionEnter(Collision Other)
// {
// if ( Other.gameObject.GetComponent( typeof(AIscript) ) != null &Other.gameObject != objPlayer ) // if we have hit a character and it is not the player
// {
// removeMe();
// }
// }
}**

  • ```*
  • Spawn Script*
  • ```*
  • *using UnityEngine;
    using System.Collections;

public class spawnEnemies : MonoBehaviour
{
public Transform Enemy;
public float enemyNumber = 10f;
public float wave = 1f;
public float enemyCount = 0f;
private float timeSpawn = 3;

// Update is called once per frame
void Update ()
{
if (enemyNumber> enemyCount)
	{
		if(timeSpawn <= Time.time)
		{
		Instantiate(Enemy,transform.position, Quaternion.identity);
		
		enemyCount +=1;
		timeSpawn +=3;
			
		}
	}
}

}**

  • ```*
  • *
  • As you can see the player ship is moving from AWSD, the aim is from the mouse pointer and the enemies are following the player - the problem is also clearly visible as the enemies are going inside each other and could be kill with 1 hit.*
  • Enemy death script*
  • ```*
  • *using UnityEngine;
    using System.Collections;

public class EnemyDeath : MonoBehaviour
{
//public GameObject ExplosionPrefab;

void OnTriggerEnter(Collider whatHitMe)
{
	if(whatHitMe.gameObject.tag=="Bullet")
	{
		
		print("Enemy Destroyed");
		Destroy (whatHitMe.gameObject);
		Destroy (this.gameObject);
		
        gameController.Score += 100;
		
	}
}

}**

  • ```*
  • Most of this scripts are from tutorials as I’m still learning.*
    - *About the power-up, I’m really stuck with this, if you could provide a base code or a tutorial… it would be very much appreciated.**
  • Regarding the enemy spawn system, should I just manually put spawn points everywhere? Or is there a better way to do this for this game type.*
  • Please guys help me out, I’m new to Unity scripting, so tutorials similar to this game would be a great help.*
  • Thank you very much for your time.*

Bump, please help guys.

i would like to help with some tips but unfortunately i’m no “scripting god”. with your requirement you excluded probably 99+% of the forum users from helping you.

Lol I am far from scripting God, but I created a space shooter, and had to deal with these problems too. I am not by my home computer, but later today I’ll show you how I handled powerups and stuff.

EDIT: ok here is my script I used for a powerup in “Asteroid Buster” for android…

using UnityEngine;
using System.Collections;

public class LaserPowerupScript : MonoBehaviour
{
	private float startTime;
	private float restSeconds;
	private float restSecondsFlicker;
	private int roundedRestSeconds;
//	private int displaySeconds;
//	private int displayMinutes;
//	private string text; 

	public float countDownSeconds = 10f;
	public float flickerAtSeconds = 7.5f;

	void Awake()
	{
//		text = string.Format ("{0:00}:{1:00}", displayMinutes, displaySeconds); 
    	startTime = Time.time;
	}

	void OnGUI()
	{
    	//make sure that your time is based on when this script was first called
		//instead of when your game started
    	var guiTime = Time.time - startTime;

    	restSeconds = countDownSeconds - (guiTime);
		restSecondsFlicker = flickerAtSeconds - (guiTime);

    	//display messages or whatever here -->do stuff based on your timer
//    	if (restSeconds == 60)
//		{
//        	print ("One Minute Left");
//    	}
    	if (restSeconds < 0)
		{
        	//print ("Time is Over");
        	Die();
    	}
		if (restSecondsFlicker < 0)
		{
			if (0==(Mathf.RoundToInt(Time.time*10) - Mathf.FloorToInt(Time.time * 10)))
					HideModel(true);
				else
					HideModel(false);
		}
		
    	//display the timer
//   		roundedRestSeconds = Mathf.CeilToInt(restSeconds);
//    	displaySeconds = roundedRestSeconds % 60;
//    	displayMinutes = roundedRestSeconds / 60; 

    	//string text = String.Format ("{0:00}:{1:00}", displayMinutes, displaySeconds); 
//    	GUI.Label (new Rect (400, 25, 100, 30), text);
	}
	
	void Update()
	{
		//Debug.Log("restSeconds= " + restSeconds);
		transform.Rotate(0, 0, 1);
	}
	
	void HideModel(bool bHidden)
	{
		Renderer[] renderers = GetComponentsInChildren<Renderer>();
		foreach(Renderer rend in renderers)
		{
			rend.enabled=!bHidden;
		}
	}
	
	void Die()
	{
		Destroy(gameObject);
	}
}

and of course you will likely need to modify this to work with your setup… but hey it worked for me, I have variations of this for other powerups (extra lives, multi-shot) but this particular one was for a laser beam… let me know if you need help with any of it.

ps: this script was attached to a gameobject, which when spawned, eventually starts flickering then disappears when no one gets it.

Thank you very much man, I’ll try this early in the morning.

On the other hand, how about my other questions mate? Could you help with that too?

Also could you provide any tutorial you used for your game? or Could you please provide the scripts for your game so I could have a look at them?

This is all personal stuff and for learning purposes.

Thank you very much for your time man. Cheers!

Huh? Are this really difficult scripting questions? I have no clue to be honest, I just can’t find any tutorial to help me with this, but all of what I wrote above are 100% from tutorials and I haven’t wrote anything myself.

I’m probably just looking for people who have some top-down space shooter experience.

I think your biggest problem is having too many questions for one post :slight_smile:

I’ll pick the easiest one …you actually already got an answer in the question. What ever your bullet speed is, add your ship velocity to it.
[/quote]

i think not. most programmers could help you with this i guess. also me albeit i’m only an average unity user i guess. thats why i wondered why you only want help from “scripting gods” and not “normal” people. sure what other people could tell you might be not as efficient or perfect as what “scripting gods” know, but it would still be an answer. i fear all those people you want to help you are far too busy with their stuff and becoming better.

i often wonder about the haughtiness of new forum members (like you). can hardly code the easiest stuff but want a perfect solution, the best way or help of only the best people. where an easy solution, a working way or an answer of an average coder could be more suited to the problem/task. but in their ignorance they don’t see it and only accept the best to become elitists more quicker i guess. its a pitty.

Man don’t take the word scripting Gods to seriously, I consider everyone better than me scripting Gods… which would be 90% of people in this forum.

Yes look at line 79+, I tried to do it with the help from the tutorial, but I still couldn’t make it work.

I actually cannot share the complete project (I like to open source most of my stuff, for others to fix problems and help others learn) only because some of it I cannot legally share openly - the powerup script was excluded from that restriction… I am sorry about that, but I will try to help with other things if you have any other specific problems. As far as the velocity adding to your bullets, that can be a little tricky, I have to do some stuff today, but when I am free I will take a look at your code and see what I can come up with.

Hey man, could I get that multi-shot power-up script off you? I just want to learn how picking up an object will trigger a power-up.

Did you managed to get a proper enemy collision? Because like I wrote above my enemies are going inside each other and can be killed with one hit.

Lastly, thank you for having a look at the bullets/speed for me.

Cheers.

Yeah I can get it, its fairly similar to the one I showed you, but the way it effects the player is different, I could get a couple snippets of that as well, but I am again not near my computer right this second, will take a bit longer, so here in a couple hours I should be able to help ya out.

Alright cool, I’m gonna start doing right now. Anyway man how about my other questions? Thanks a lot by the way.

Ok so here’s how the multi-shot powerup works:

  • First the player (floating around rigidbody box with graphics - locked to 2d movement) shoots up some asteroids (with its basic projectile)
  • Second the asteroid randomly decides if it does or doesn’t drop a powerup.
  • Third if the asteroid randomly DOES drop one (instantiate it) then a randomly selected powerup, with greater weight to the less powerful ones, starts counting down a timer to its own self destruction.
  • Fourth (assuming the player picked up the powerup by flying into it) the powerup enables a bool in the playerscript which allows the projectile to change (if its a weapon powerup) or if its an extra life, it simply adds one life to the players life count (assuming they dont already have max lives).
    Fourth (assuming the player takes too long, or ignores the powerup) the powerups renderer starts flickering, and eventually completely dissapears (destroy()'s itself).

So, first the asteroid has its OnCollisionEnter take information from the other collision:

void OnCollisionEnter(Collision other)
	{ ...

and then, if none of the certain types of powerups exist already, it might spawn one:

if(GameObject.FindGameObjectsWithTag("LaserPowerup").Length == 0)
			{
				if(Random.Range(1, 15) == 1)
				{
					Instantiate(LaserPowerup, transform.position, transform.rotation);
					return;
				}
			}
		
			if(GameObject.FindGameObjectsWithTag("MultiShotPowerup").Length == 0)
			{
				if(Random.Range(1, 25) == 1)
				{
					Instantiate(MultiShotPowerup, transform.position, transform.rotation);
					return;
				}
			}
			
			if(GameObject.FindGameObjectsWithTag("ShieldPowerup").Length == 0)
			{
				if(Random.Range(1, 20) == 1)
				{
					Instantiate(ShieldPowerup, transform.position, transform.rotation);
					return;
				}
			}

and lets say that it spawns a multishot powerup (with this script attached):

using UnityEngine;
using System.Collections;

public class MultiShotPowerupScript : MonoBehaviour
{
	private float startTime;
	private float restSeconds;
	private float restSecondsFlicker;
	private int roundedRestSeconds;
//	private int displaySeconds;
//	private int displayMinutes;
//	private string text; 

	public float countDownSeconds = 10f;
	public float flickerAtSeconds = 7.5f;

	void Awake()
	{
//		text = string.Format ("{0:00}:{1:00}", displayMinutes, displaySeconds); 
    	startTime = Time.time;
	}

	void OnGUI()
	{
    	//make sure that your time is based on when this script was first called
		//instead of when your game started
    	var guiTime = Time.time - startTime;

    	restSeconds = countDownSeconds - (guiTime);
		restSecondsFlicker = flickerAtSeconds - (guiTime);

    	//display messages or whatever here -->do stuff based on your timer
//    	if (restSeconds == 60)
//		{
//        	print ("One Minute Left");
//    	}
    	if (restSeconds < 0)
		{
        	//print ("Time is Over");
        	Die();
    	}
		if (restSecondsFlicker < 0)
		{
			if (0==(Mathf.RoundToInt(Time.time*10) - Mathf.FloorToInt(Time.time * 10)))
					HideModel(true);
				else
					HideModel(false);
		}
		
    	//display the timer
//   		roundedRestSeconds = Mathf.CeilToInt(restSeconds);
//    	displaySeconds = roundedRestSeconds % 60;
//    	displayMinutes = roundedRestSeconds / 60; 

    	//string text = String.Format ("{0:00}:{1:00}", displayMinutes, displaySeconds); 
//    	GUI.Label (new Rect (400, 25, 100, 30), text);
	}
	
	void Update()
	{
		//Debug.Log("restSeconds= " + restSeconds);
		transform.Rotate(0, 0, 1);
	}
	
	void HideModel(bool bHidden)
	{
		Renderer[] renderers = GetComponentsInChildren<Renderer>();
		foreach(Renderer rend in renderers)
		{
			rend.enabled=!bHidden;
		}
	}
	
	void Die()
	{
		Destroy(gameObject);
	}
}

then it waits patiently (spinning around in a circle slowly) until player hits it (or it destroy()'s itself that is) - and when the player collides with it, it “triggers” something to happen (with OnTriggerEnter, because the powerup is set up as trigger):

void OnTriggerEnter(Collider other)
	{
		if(Enabled)
		{
			if(other.gameObject.tag == "ExtraLife")
			{
				GameObject world = GameObject.Find("WorldLogic");
				GameLogicScript gls = world.GetComponent<GameLogicScript>();
				gls.AddExtraLife();
				Destroy(GameObject.FindGameObjectWithTag("ExtraLife"));
			}
			if(other.gameObject.tag == "LaserPowerup")
			{
				lasersEnabled = true;
				Destroy(GameObject.FindGameObjectWithTag("LaserPowerup"));
			}
			if(other.gameObject.tag == "MultiShotPowerup")
			{
				multiShotEnabled = true;
				Destroy(GameObject.FindGameObjectWithTag("MultiShotPowerup"));
			}
			if(other.gameObject.tag == "ShieldPowerup")
			{
				shieldEnabled = true;
				Destroy(GameObject.FindGameObjectWithTag("ShieldPowerup"));
			}
		}
	}

and, since our “multiShotEnabled” bool becomes true, this part of our shooting section of the player script starts working:

if(multiShotEnabled  FireHit  Time.time > nextShotTime)
				{
					nextShotTime = Time.time + (fireInterval * 1.2f); // slightly slower refire rate than single shots
					if (go)//GameObject.FindWithTag("Player Tilt"))
					{
						Vector3 newPos1 = new Vector3(-0.05f,0.0f,0.0f);
						Vector3 newPos2 = new Vector3(-0.3f,0.0f,0.0f);
						Vector3 newPos3 = new Vector3(0.3f,0.0f,0.0f);
						newPos1 = go.transform.TransformPoint(newPos1);
						newPos2 = go.transform.TransformPoint(newPos2);
						newPos3 = go.transform.TransformPoint(newPos3);
						
						GameObject projectile1 = Instantiate(Shot, newPos1, go.transform.rotation) as GameObject;
						GameObject projectile2 = Instantiate(Shot, newPos2, go.transform.rotation) as GameObject;
						GameObject projectile3 = Instantiate(Shot, newPos3, go.transform.rotation) as GameObject;
						Physics.IgnoreCollision(projectile1.collider, go.collider);
						Physics.IgnoreCollision(projectile2.collider, go.collider);
						Physics.IgnoreCollision(projectile3.collider, go.collider);
						Physics.IgnoreCollision(projectile1.collider, projectile2.collider);
						Physics.IgnoreCollision(projectile1.collider, projectile3.collider);
						Physics.IgnoreCollision(projectile2.collider, projectile3.collider);
						projectile2.transform.Rotate(0, 0, -10);
						projectile3.transform.Rotate(0, 0, 10);
					}
				}

and as you see, it instantiates three seperate projectiles, and ensures they dont collide to each other (because they would lol) before flying off into space some predefined distance and destroy()'ing themselves, or hitting an asteroid.

So there you have it. Multi-Shot powerup. I guess its worth noting, I am just seeing that it may be possible to spawn two (or more) powerups - or maybe I had some way to prevent that elsewhere, not sure, cant remember. anyway odds are against it happening, but if you used ELSE if statements after the first powerup random selection, it would take care of it.

and for these I’ll touch on them real quickly:
Q) Enemies collision
A) Physics! Get rigidbodies on all these floaty space enemies (dont ever have a whole boatload running at once or its costly to mobile devices…not sure of ur launch platform) and then when any two of them hit, they will bounce around. The only thing you might wanna do is some kinda “crashed” appearance change if necessary, and maybe some spark particles flying off the ships and such. If you dont rely on the physics engine (maybe you have proprietary movement setup) then its gonna mean detecting collisions and then taking the normal of the hit, and inverting it so your velocity “bounces” off the other object - this can be tricky!
Q) Bullets move slow while the ship is moving forward… I can’t seem to make the velocity of the ship + the bullet work…
A) did you take any attempts at adding the velocity of the ship into the default velocity of the projectile? I could maybe help you sort out the problem if you show me the part of your script that starts out the movement of the projectile.
Q) Enemy spawn, so far I got a individual spawn, I probably need the enemies to spawn from the camera…because this game is an open world adventure… but I need different waves of enemies spawning.
A) this is really situational, if your running like mobile, you need to be real careful on your max possible active units at a time, especially if your relying on physics to drive things. In asteroid buster I never moved the camera, and asteroids spawned in from the edge of the screen. This made it easy to handle them wrapping around and stuff (like classic asteroids gameplay) which was what I was going for. In your case though, sounds like you need something more complex, that considers the players position in the overall world, and only spawns enemies within a certain range from the player. as for that, its pretty much gonna require you writing something unique to your gameplay, because if your flying around from different locations or something, you will need to prevent enemies from spawning in certain areas, and such. Maybe big areas are always spawning enemies if the player is flying through, but only to a certain maximum, and never on screen where the player can see it happen.

Enemy collisions - I have all the enemies with rigidbodies, colliders and yet they still mesh together in one spot. You can find the AI follow script on line 93

Bullets slow movement - Yes I tried adding the ship velocity to it but nothing happens, line 79 AI script

AI spawn, yes I’ll look for a tutorial that spawns enemies only if it enters the specific region.

Also mate, do you have a tutorial for a booster? Like if I press SPACE bar my ship will move faster? Base on line 67 of the AI script.

Also guys…how do I emit the instantiate in 360 degrees around the origin?

Are the enemies triggers? or is maybe the player set as trigger? as far as a booster goes, its pretty straightforward. I would have an if statement like if(regularSpeed) // regular speed is a bool
{
// have player speed set as its default speed
}
else if(boostSpeed) // boost speed is another bool (decided by which keys are hit at the time)
{
// something like currentMovementSpeed = Lerp(regularMovementSpeed, boostMovementSpeed, 0.5f); // this would slowly increase up to boost speed
// something like rigidbody.addforce(movementDirection, currentMovementSpeed); // this applys that float to the rigidbody
}

but thats pseudo code you will need to correct it, but you get the idea right?

I am not sure what you mean by instantiate in 360 degrees around origin? like origin of the world? and by instantiate 360 degrees around it, like a certain angle from it? a certain distance a certain angle from it?

See I want the power-ups to come out from the ship, like in my Bullets, the prefab is instantiated from a spot and then force added to it for the bullet to go forward (unity instantiate tutorial). Now I want the same kind of spawn system for the power-ups where it will shoot out from the ship (randomly 360 degrees around it, to make it unpredictable) and this spawn of power-ups from the ship will be controlled by a timer and will check if their are 4 power-ups present, if not, it will spawn until there are 4 power-ups in the screen.

Thank you so much man!

No problem, I always like to see aspiring developers getting to know unity better, because the more there are - the more games I can play later haha.

Anyway for an effect like that, you could do something similar to a bullet, where it starts out just the same, but in a random direction instead of straight forward, and perhaps have it lerp to a certain distance from the ship before slowing to a stop (or just keep on going if you like). Maybe if you have it hit a certain distance from its spawn, then have it change direction and kinda lerp back and forth between random points in an area, could make it harder to collect it.