Only one gameobject being affected by script - c#

Making a state machine AI "game" I have 3 states Movement, Combat, and View. They all work very well, now I'm making a flee (by the way if anyone has any good links to tutorials or info that they have off hand I would love that) state so I want to make all three previous state in their Idle mode. Which works perfectly when I have 1 AI. As soon as I put the rest (there is 6 total now) it will still only affect 1, but then after some time it will "release" I guess it the best term the script and just goes back to the three states that are supposed to be idle. I think that in my Coin script I am saying find and I think it needs to be something else, I'm just not sure if that's even right but based off of my previous experiences that's usually the case with Unity. I'll post some code, but here's some info that may help your eyes by not having to read through everything:
-I have a bool set up in my AIClass that is false until one of my gameobjects collides with a 'coin', and coin is jsut a gameobject i put in my game to test out my AI behaviors. When that bool is true, in my update in my AIClass(sorry it's at the very bottom of the script you can scroll down, but I had to put other code just in case I was doing something in that to cause my problem.) It sets the state of MovementState to Idle, CombatState to Idle and ViewState to Idle.
-Also, when that bool is false is the only time that the call for the transition of states occur. For example, normally the AI will search around trying to find player, if they find him they go near him, and if they are in a certain distance they fire. Pretty simple. The movement between those states happens at the end of each IENumerator when the 'NextMovementState()' or 'NextCombatState()' or 'NextViewState()' are called. So when the bool is true those should never be called, halting the AI from moving to another state other than Idle (to what it's set at when the bool is true in the update).
And this works fine when I have only 1 AI in the game.
CoinScript.cs
using UnityEngine;
using System.Collections;
public class CoinScript : MonoBehaviour {
private AIClass a;
// Use this for initialization
void Start () {
a = GameObject.Find ("Enemy").GetComponent<AIClass>();
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter(Collision collision)
{
if (collision.collider)
{
if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyProjectile")
{
Physics.IgnoreCollision(rigidbody.collider,collision.collider);
//Debug.Log ("Enemy");
}
if(collision.gameObject.tag == "Player")
{
Debug.Log ("triggered!");
a.fleeBool = true;
Destroy(gameObject);
}
}
}
}
AIClass.cs
using UnityEngine;
using System.Collections;
public class AIClass : MonoBehaviour
{
public NavMeshAgent agent;
//Ammo in gun before reloading is required
public int ammo = 30;
public int maxAmmo = 30;
//Number of bullets a gun fires in sequence on 1 trigger pull
public int chamber = 3;
public int maxChamber = 3;
//Pause between bursts or mouse presses, set to 0 for fully automatic
public double chamberTime = 120;
//How fast a gun fires in RPS
public int fireRate = 7;
public int fireTimer = 0;
//How fast a gun can reload
public int reloadTime = 3;
public int reloadTimer = 0;
//Number of bullets fired per shot
public int bulletsFired = 1;
public GameObject bulletClone;
//Acceptable degrees as to which the AI will begin firing at its target
public int firingAngle = 5;
//Vision cone of degrees to left and right
public int visionAngle = 35;
public int visionDistance = 100;
public int vRotationSpeed = 3;
public int vIdleTimer = 0;
public int vIdleTime = 300;
public int searchTimer = 0;
public int searchTime = 300;
public int mIdleTimer = 0;
public int mIdleTime = 300;
public bool isFocusedOnPlayer = false;
public bool seesPlayer = false;
//
public bool fleeBool;
public bool flee;
public enum MovementState
{
MSearch,
MMoving,
MIdle,
}
public enum CombatState
{
CFiring,
CReloading,
CIdle,
}
public enum ViewState
{
VSearch,
VFocus,
VIdle,
}
public enum FleeState
{
FSearch,
FMoving,
FIdle
}
public CombatState combatState;
public ViewState viewState;
public MovementState movementState;
public FleeState fleeState;
//Search state (knows where player is and will head to the player's location)
IEnumerator MSearchState ()
{
mIdleTimer = 0;
int stuckTimer = 0;
while (movementState == MovementState.MSearch)
{
//I've arrived at my location, if idle too long, then go back to idle state
if(Vector3.Distance(transform.position,agent.destination) < 3)
mIdleTimer++;
//I'm stuck and haven't moved in a while, go back to idle state
if(agent.velocity.magnitude < 1)
stuckTimer++;
if(seesPlayer || mIdleTimer > mIdleTime + 200 || stuckTimer > 300)
{
agent.destination = transform.position;
movementState = MovementState.MIdle;
}
yield return 0;
}
if (!flee) {
NextMovementState();
}
}
//Wander state
IEnumerator MMovingState ()
{
while (movementState == MovementState.MMoving)
{
//Wander code... Create a random angle and convert it to radians
float randomAngle = (float)(3.14/180)*Random.Range(0,360);
//Normalize direction vector, as we will be using it to calculate where we place the circle
Vector3 tempV = agent.velocity;
Vector3.Normalize (tempV);
//Using our relative position, 5 units in front of us. Use the generated angle to find the point on the circle that we want to go to
agent.destination = transform.position + tempV * 3 + new Vector3(Mathf.Cos (randomAngle)*3,0,Mathf.Sin (randomAngle)*3);
//Check to see if we are within the arena bounds, if not, push our projected vector back inside
if(agent.destination.x > 24)
agent.destination = agent.destination + new Vector3(-7,0,0);
if(agent.destination.x < -24)
agent.destination = agent.destination + new Vector3(7,0,0);
if(agent.destination.z > 24)
agent.destination = agent.destination + new Vector3(0,0,-7);
if(agent.destination.z < -24)
agent.destination = agent.destination + new Vector3(0,0,7);
if(seesPlayer)
{
agent.destination = transform.position;
movementState = MovementState.MIdle;
}
yield return 0;
}
if (!flee) {
NextMovementState ();
}
}
//Not moving, if I don't see the player for awhile, then go wander
IEnumerator MIdleState ()
{
mIdleTimer = 0;
while (movementState == MovementState.MIdle)
{
if(seesPlayer)
mIdleTimer = 0;
else
mIdleTimer++;
if(mIdleTimer > mIdleTime + Random.Range (-100,100))
movementState = MovementState.MMoving;
yield return 0;
}
if (!flee) {
NextMovementState ();
}
}
//Visual search state, randomly look around and check to see if we see the player
IEnumerator VSearchState ()
{
Transform target = GameObject.FindWithTag ("Player").transform;
Vector3 targetPosition = target.position;
while (viewState == ViewState.VSearch)
{
searchTimer--;
//Vision Cone calculation
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
//If player is within vision cone then proceed
if (angle < visionAngle)
{
//Check to see if there are any object between player and myself
RaycastHit hit;
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
seesPlayer = true;
viewState = ViewState.VFocus;
}
}
}
//Look in another direction
if(searchTimer < 0)
{
searchTimer = searchTime + Random.Range (-100,100);
targetPosition = new Vector3(Random.Range (-100,100),transform.position.y,Random.Range (-100,100));
}
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(targetPosition - transform.position), vRotationSpeed*Time.deltaTime);
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Focus on player
IEnumerator VFocusState ()
{
Transform target = GameObject.FindWithTag ("Player").transform;
while (viewState == ViewState.VFocus)
{
//Vision Cone calculation
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
if (angle > visionAngle)
viewState = ViewState.VIdle;
else
{
RaycastHit hit;
//Check if there are any objects in the way
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
//Tell other AI where player is
GameObject[] objArray = GameObject.FindGameObjectsWithTag ("Enemy");
AIClass[] enemyArray = new AIClass[objArray.Length];
for(int i = 0; i < enemyArray.Length; i++)
{
enemyArray[i] = (AIClass)objArray[i].GetComponent(typeof(AIClass));
if(i >= enemyArray.Length/2)
enemyArray[i].agent.destination = target.position;
else
enemyArray[i].agent.destination = target.position + target.forward*5;
enemyArray[i].movementState = MovementState.MSearch;
}
seesPlayer = true;
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(target.position - transform.position), vRotationSpeed*Time.deltaTime);
//Check to see player is within sights of the gun
if (angle < firingAngle)
isFocusedOnPlayer = true;
else
isFocusedOnPlayer = false;
}
else
{
//I no longer see the player
seesPlayer = false;
viewState = ViewState.VIdle;
isFocusedOnPlayer = false;
}
}
}
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Visual idle state, basically the ai is just looking forward
IEnumerator VIdleState ()
{
vIdleTimer = 0;
Transform target = GameObject.FindWithTag ("Player").transform;
while (viewState == ViewState.VIdle)
{
//Vision cone calculation
vIdleTimer++;
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
//Check to see if there is an object is between the ai and the player
if (angle < visionAngle)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
seesPlayer = true;
viewState = ViewState.VFocus;
}
}
}
if(vIdleTimer > vIdleTime)
viewState = ViewState.VSearch;
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Firing gun state
IEnumerator CFiringState ()
{
while (combatState == CombatState.CFiring)
{
if(!isFocusedOnPlayer)
combatState = CombatState.CIdle;
fireTimer--;
if(ammo > 0)
{
if(chamber > 0)
{
if(fireTimer <= 0)
{
for(int i = 0; i < bulletsFired;i++)
{
GameObject temp = (GameObject) Instantiate (bulletClone,transform.position + transform.forward,transform.rotation);
temp.rigidbody.AddForce(transform.forward*500);
}
fireTimer = 60 / fireRate;
ammo--;
chamber--;
}
}
else
{
chamber = maxChamber;
fireTimer = (int)(60/chamberTime);
}
}
else
{
combatState = CombatState.CReloading;
}
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
IEnumerator CReloadingState ()
{
reloadTimer = reloadTime * 60;
while (combatState == CombatState.CReloading)
{
reloadTimer--;
if(reloadTimer <= 0)
{
ammo = maxAmmo;
combatState = CombatState.CIdle;
}
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
IEnumerator CIdleState ()
{
while (combatState == CombatState.CIdle)
{
if(isFocusedOnPlayer)
combatState = CombatState.CFiring;
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
void Start ()
{
fleeBool = false;
flee = false;
NextCombatState();
NextViewState();
NextMovementState();
}
void NextMovementState()
{
string methodName = movementState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextCombatState ()
{
string methodName = combatState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextViewState ()
{
string methodName = viewState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextFleeState()
{
string methodName = viewState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void Update()
{
Debug.DrawLine(transform.position, transform.position+transform.forward*5, Color.red);
if (fleeBool == true)
{
flee = true;
}
if (flee == true)
{
Debug.Log ("flee is true");
combatState = CombatState.CIdle;
movementState = MovementState.MIdle;
viewState = ViewState.VIdle;
Debug.Log ("End of idles");
}
}
}

You can use GameObject.FindObjectsOfType() or GameObject.FindGameObjectsWithTag

you can do that with store all the AIClass into array and then loop it become specific, so every enemy can affected
AIClass[] AIObject = GameObject.Find("Enemy").GetComponents<AIClass>();
foreach(AIClass a in AIObject ){
//do something with a
}
it should work.

Related

How and where in the code should I use the loop bool flag to decide if to loop or to make once movement between the waypoints?

The goal is to be able to decide if to loop or to move only once between the waypoints.
I added the loop bool flag for that.
Added the most details I can.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AI;
public class Move : MonoBehaviour
{
public Transform[] targets;
public LineRenderer lineRenderer;
public float speed;
public bool go = false;
public bool countOrigPosAsWaypoint = true;
public bool startFromFirstPositionOnStart = false;
public bool goForward = true;
public bool loop = true;
private List<Vector3> pos = new List<Vector3>();
private List<Vector3> positions = new List<Vector3>();
private int index = 0;
private List<GameObject> objectsToMoveCopy = new List<GameObject>();
// Start is called before the first frame update
void Start()
{
if (lineRenderer != null)
{
pos = GetLinePointsInWorldSpace();
}
else
{
if (countOrigPosAsWaypoint == true)
{
pos.Add(transform.position);
}
for (int i = 0; i < targets.Length; i++)
{
pos.Add(targets[i].position);
}
}
if (startFromFirstPositionOnStart == true)
{
transform.position = pos[index];
}
if (pos.Count <= 1)
{
Debug.LogWarning("Targets list count must be more then 1");
}
}
List<Vector3> GetLinePointsInWorldSpace()
{
positions = new Vector3[lineRenderer.positionCount].ToList();
//Get the positions which are shown in the inspector
lineRenderer.GetPositions(positions.ToArray());
//the points returned are in world space
return positions;
}
// Update is called once per frame
void Update()
{
if (go == true && pos.Count > 1)
{
Moving();
}
}
void Moving()
{
Vector3 newPos = transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= pos.Count - 1;
if (!atLastOne) index++;
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne) index--;
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
transform.position = newPos;
}
}
If true make a loop between the waypoints either backward or forward and if false just move forward or backward once and stop the last/first waypoint.
I'ld say e.g. at
if (!atLastOne)
{
index++;
}
else if(!loop)
{
stillTraveling = false;
}
else
{
index--;
goForward = false;
}
and accordingly
if (!atFirstOne)
{
index--;
}
else if(!loop)
{
stillTraveling = false;
}
else
{
index++;
goForward = true;
}
And probably remove the current
else
{
stillTraveling = false;
}
as it will be the case most of the time between the points.
In general though: Currently this will all happen in one single frame without any animation... This should probably rather happen in a Coroutine or only do one step at a time .. not in a while loop at all.

How to stop player from pushing NPCs while moving

my problem today is simple (two problems if you count the fact that English isn't my first language), yet I can't manage to get a hold of it. I'm trying to make an up down game in c# and I'm trying to improve the movement scripts before working on anything else (since I don't want to resolve major bugs later).
The problem is that as soon as the player comes in contact with the NPC, it should stop moving in its general direction (it can move in 8 directions, using combinations of the W A S D keys). The NPC movement doesn't give any problems, it stops moving as soon as it perceives the player. Instead, when the player collides with the NPC it keeps on moving in that direction pushing it for what feels like half a second before stopping (as it should). So, to summarize, it doesn't immediately stop, which is unnerving since I've tried many things to make it stop (including freezing the position of the NPC but that just made things worse).
Now the codes:
The NPC movement code:
public class NPCFreeMovement : MonoBehaviour
{
public float speed = 2f; //how fast does the npc move
public float maxIdleTime = 3f; //max time the npc spends idling
public float maxChooseTime = 20f; //max time he spends moving
public float chooseDirTime = 0; //if 0, he chooses a direction
//possible directions
readonly Vector3[] directions = {Vector3.down, new Vector3(-0.5f, -0.5f, 0), Vector3.left, new Vector3(-0.5f, 0.5f, 0), Vector3.up,
new Vector3(0.5f, 0.5f, 0), Vector3.right, new Vector3(0.5f, -0.5f, 0)};
public int dir; //current direction
public bool canMove = true; //pretty self explainatory
public bool idle = true; //is the npc idle
public bool chase = false; //is the npc chasing after the player
public Vector3 goTo; //where to go if it's chasing after something
void Start()
{
StartCoroutine(Idle(maxIdleTime));
}
void Update()
{
chase = GetComponent<NPCLookForPlayerScript>().found;
if(canMove && !idle)
{
//move in the chosen direction
transform.position = Vector3.MoveTowards(transform.position, transform.position + directions[dir], Time.deltaTime * speed);
if (chooseDirTime > 0) //decrease movement time
{
chooseDirTime -= Time.deltaTime;
}
else
{
if(chase) StartCoroutine(Idle(0));
else StartCoroutine(Idle(Random.Range(0, maxIdleTime)));
}
}
}
//npc goes idle, then chooses a direction
public IEnumerator Idle(float f)
{
idle = true;
yield return new WaitForSeconds(f);
idle = false;
//here he chooses the direction depending of wether he's roaming or chasing
if (chase)
{
ChooseDirection();
chooseDirTime = maxChooseTime/4;
}
else
{
dir = Random.Range(0, directions.Length);
chooseDirTime = maxChooseTime;
}
}
//chooses a direction to take
void ChooseDirection()
{
Vector3 v = goTo - transform.position; //to check where to go
if (Mathf.Abs(v.x) <= 0.5)
{
if (v.y < 0) dir = 0; //go down
else dir = 4; //go up
}
if (Mathf.Abs(v.y) <= 0.5)
{
if (v.x < 0) dir = 2; //go left
else dir = 6; //go right
}
if (v.x < 0.5 && v.y < 0.5) dir = 1; //go down/left
if (v.x < 0.5 && v.y > 0.5) dir = 3; //go up/left
if (v.x > 0.5 && v.y > 0.5) dir = 5; //go up/right
if (v.x > 0.5 && v.y < 0.5) dir = 7; //go down/right
}
void OnCollisionEnter2D(Collision2D c)
{
if(c.gameObject.tag == "Obstacle") //stop and choose a new direction
{
StartCoroutine(Idle(Random.Range(0, maxIdleTime)));
}
if (c.gameObject.tag == "Player") //stop
{
canMove = false;
}
}
private void OnCollisionExit2D(Collision2D c)
{
if (c.gameObject.tag == "Player") //resume chasing the player
{
canMove = true;
}
}
}
The player's movement script:
public class PlayerFreeMovement : MonoBehaviour
{
public float speed = 2.0f; //movement speed
//where he's facing
public bool up;
public bool down;
public bool left;
public bool right;
public bool idle; //false if a movement button is pressed
public bool canMove = true;
//movement direction
public float dx;
public float dy;
public Vector3 v;
CollisionScript cs; //collision script
void Start()
{
down = true;
cs = GetComponent<CollisionScript>();
}
void Update() //move stickman in the direction of the keys and maintain the direction he's facing with animations
{
dx = 0;
dy = 0;
if (!(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S))) //check if idle
{
idle = true;
v = new Vector3();
}
else //the player's moving
{
idle = false;
AllFalse();
//set dx and dy
if (canMove && Input.GetKey(KeyCode.D))
{
if(!cs.hitRight) dx = 1;
right = true;
}
if (canMove && Input.GetKey(KeyCode.A))
{
if (!cs.hitLeft) dx = -1;
left = true;
}
if (canMove && Input.GetKey(KeyCode.W))
{
if (!cs.hitUp) dy = 1;
up = true;
}
if (canMove && Input.GetKey(KeyCode.S))
{
if (!cs.hitDown) dy = -1;
down = true;
}
//create the motion vector
v = new Vector3(dx, dy, 0);
if(dx !=0 && dy != 0)
{
v = v / 2;
}
}
//move
transform.position = Vector3.MoveTowards(transform.position, transform.position + v, Time.deltaTime * speed);
}
//avoid bug by deactivating all direction booleans before changing one
void AllFalse()
{
up = false;
down = false;
left = false;
right = false;
}
}
And finally, the collision script used to detect collisions in its path
public class CollisionScript: MonoBehaviour
{
//where is the wall
public bool hitDown= false;
public bool hitLeft = false;
public bool hitRight = false;
public bool hitUp = false;
//gizmos
public float collisionRadius = 0.5f;
public Vector2 downOffset = new Vector2(0, -0.5f);
public Vector2 rightOffset = new Vector2(0, 0.5f);
public Vector2 leftOffset = new Vector2(-0.5f, 0);
public Vector2 upOffset = new Vector2(0, 0.5f);
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
hitDown = Physics2D.OverlapCircle((Vector2)transform.position + downOffset, collisionRadius).gameObject!=gameObject;
hitRight = Physics2D.OverlapCircle((Vector2)transform.position + rightOffset, collisionRadius).gameObject != gameObject;
hitLeft = Physics2D.OverlapCircle((Vector2)transform.position + leftOffset, collisionRadius).gameObject != gameObject;
hitUp = Physics2D.OverlapCircle((Vector2)transform.position + upOffset, collisionRadius).gameObject != gameObject;
}
void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere((Vector2)transform.position + downOffset, collisionRadius);
Gizmos.DrawWireSphere((Vector2)transform.position + rightOffset, collisionRadius);
Gizmos.DrawWireSphere((Vector2)transform.position + leftOffset, collisionRadius);
Gizmos.DrawWireSphere((Vector2)transform.position + upOffset, collisionRadius);
}
}

Unity2D no bullet trail while shooting at enemy

https://gyazo.com/0a29918f513316fc4143a5ff76095bd3
This is how it looks visually.
That's my shooting weapon code:
public class Weapon : MonoBehaviour {
public float fireRate = 0;
public float maxDamage = 10;
public LayerMask whatToHit ;
public Transform BulletTrailPrefab;
public Transform MuzzleFlashPrefab;
public Transform HitPrefab;
float timeToSpawnEffect = 0;
public float effectSpawnRate = 10;
float timeToFire = 0;
Transform firePoint;
// Use this for initialization
void Awake () {
firePoint = transform.FindChild("FirePoint");
if(firePoint == null)
{
Debug.LogError("No FirePoint");
}
}
// Update is called once per frame
void Update () {
if(fireRate == 0)
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}else
{
if(Input.GetButton("Fire1") && Time.time > timeToFire)
{
timeToFire = Time.time + 1 / fireRate;
Shoot();
}
}
}
void Shoot()
{
Vector2 mousePosition = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 firePointPosition = new Vector2(firePoint.position.x, firePoint.position.y);
RaycastHit2D hit = Physics2D.Raycast(firePointPosition,mousePosition - firePointPosition,100,whatToHit);
Debug.DrawLine(firePointPosition, (mousePosition - firePointPosition) * 100,Color.cyan);
if(hit.collider != null)
{
Debug.DrawLine(firePointPosition, hit.point, Color.red);
Enemy enemy = hit.collider.GetComponent<Enemy>();
if(enemy != null)
{
enemy.DamageEnemy(Random.Range(maxDamage/2,maxDamage));
// Debug.Log("we hit" + hit.collider.name + " and did: " + maxDamage + " damage");
}
}
if (Time.time >= timeToSpawnEffect)
{
Vector3 hitPos;
Vector3 hitNormal;
if (hit.collider == null)
{
hitPos = (mousePosition - firePointPosition) * 30;
hitNormal = new Vector3(9999, 9999, 9999);
}
else
{
hitPos = hit.point;
hitNormal = hit.normal;
}
Effect(hitPos,hitNormal);
timeToSpawnEffect = Time.time + 1 / effectSpawnRate;
}
}
void Effect(Vector3 hitPos, Vector3 hitNormal)
{
Transform trail = Instantiate(BulletTrailPrefab,firePoint.position,firePoint.rotation) as Transform;
LineRenderer lr = trail.GetComponent<LineRenderer>();
if(lr != null)
{
// Set positions
lr.SetPosition(0, firePoint.position);
lr.SetPosition(1, hitPos);
}
Destroy(trail.gameObject, 0.035f);
if (hitNormal != new Vector3(9999, 9999, 9999))
{
Transform hitParticle = Instantiate(HitPrefab, hitPos, Quaternion.FromToRotation(Vector3.right,hitNormal)) as Transform;
hitParticle.parent = transform.parent;
Destroy(hitParticle.gameObject, 0.3f);
}
Transform clone = Instantiate(MuzzleFlashPrefab, firePoint.position, firePoint.rotation);
clone.parent = firePoint;
float size = Random.Range(0.3f, 0.5f);
clone.localScale = new Vector3(size, size, size);
Destroy(clone.gameObject, 0.02f);
}
}
I've been trying to figure it out what's wrong for hours now. Checked the code just too many times, don't know how to google this problem. Just can't understand why it's hitting everything except that spaceship..
Don't know what other information you might need so tell me if you need something more.

Player getting stuck on the map

I made my first game in unity,it is running smoothly.
It has a player and aliens and a map as usual.
sometimes the player gets stuck and does not move forward,
even though the animation of player moving forward runs and his legs keeps moving but still it doesn't move
I have to move in other directions and then it can pass through that point where it got stuck
It happens randomly and not on any fixed spot.
and I am not able to figure out why this is happening
I tried to make the map again but still its there
Any suggestions would be a great help.
ublic class Player : MonoBehaviour {
public float speed = 10f;
public Vector2 maxVelocity = new Vector2(3, 5);
public bool standing;
public float jetSpeed = 15f;
public float airSpeedMultiplier = .3f;
public AudioClip leftFootSound;
public AudioClip rightFootSound;
public AudioClip thudSound;
public AudioClip rocketSound;
public Vector3 PlayerDirection = new Vector3(1,1,1);
public int ArtifactCount = 0;
private Animator animator;
private PlayerController controller;
void Start(){
controller = GetComponent<PlayerController> ();
animator = GetComponent<Animator> ();
}
void PlayLeftFootSound(){
if (leftFootSound)
AudioSource.PlayClipAtPoint (leftFootSound, transform.position);
}
void PlayRightFootSound(){
if (rightFootSound)
AudioSource.PlayClipAtPoint (rightFootSound, transform.position);
}
void PlayRocketSound(){
if (!rocketSound || GameObject.Find ("RocketSound"))
return;
GameObject go = new GameObject ("RocketSound");
AudioSource aSrc = go.AddComponent<AudioSource> ();
aSrc.clip = rocketSound;
aSrc.volume = 0.7f;
aSrc.Play ();
Destroy (go, rocketSound.length);
}
void OnCollisionEnter2D(Collision2D target){
if (!standing) {
var absVelX = Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x);
var absVelY = Mathf.Abs(GetComponent<Rigidbody2D>().velocity.y);
if(absVelX <= .1f || absVelY <= .1f){
if(thudSound)
AudioSource.PlayClipAtPoint(thudSound, transform.position);
}
}
}
// Update is called once per frame
void Update () {
var forceX = 0f;
var forceY = 0f;
var absVelX = Mathf.Abs (GetComponent<Rigidbody2D>().velocity.x);
var absVelY = Mathf.Abs (GetComponent<Rigidbody2D>().velocity.y);
if (absVelY < .2f) {
standing = true;
} else {
standing = false;
}
if (controller.moving.x != 0) {
if (absVelX < maxVelocity.x) {
forceX = standing ? speed * controller.moving.x : (speed * controller.moving.x * airSpeedMultiplier);
PlayerDirection = transform.localScale = new Vector3 (forceX > 0 ? 1 : -1, 1, 1);
}
animator.SetInteger ("AnimState", 1);
} else {
animator.SetInteger ("AnimState", 0);
}
if (controller.moving.y > 0) {
PlayRocketSound();
if (absVelY < maxVelocity.y)
forceY = jetSpeed * controller.moving.y;
animator.SetInteger ("AnimState", 2);
} else if (absVelY > 0) {
animator.SetInteger("AnimState", 3);
}
GetComponent<Rigidbody2D>().AddForce (new Vector2 (forceX, forceY));
}
}
Thanks
You should check that the point you are going is not outside your map.
I think that when you are adding forces to the rigidbody you can add "too much" forces and that rigidbody collides with something and after that it get stacked.
Edit:
Check the OnCollisionEnter, OnCollisionStay and Exit also the triggers.
http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnCollisionEnter.html

How to make Bullet initiate from the direction the player is in

I am making 2D game in Unity.
In this I wanted to add a bullet with a limited number of shots.
The bullet fires in the direction in which the player is but always initiate from the right side even if the player is facing left side. And I have limited the bullet count to 3.
How do I put delay in between the occurrence of the bullets?
1st Script (Bullet)
public class Bullet : MonoBehaviour {
private Player player;
public float speed = 1f;
public int abc = 2;
// Use this for initialization
void Start () {
player = GameObject.Find ("Player").GetComponent<Player> ();
if (player.aa.x == transform.localScale.x)
abc = 1;
}
// Update is called once per frame
public void Update () {
if (abc == 1)
rigidbody2D.velocity = new Vector3 (transform.localScale.x, 0, 1) * speed;
else
rigidbody2D.velocity = new Vector3 (transform.localScale.x, 0, 1) * speed;
}
}
2nd Script (Player)
public class Player : MonoBehaviour {
public float speed = 10f;
public Vector2 maxVelocity = new Vector2(3, 5);
public bool standing;
public float jetSpeed = 15f;
public float airSpeedMultiplier = .3f;
public AudioClip leftFootSound;
public AudioClip rightFootSound;
public AudioClip thudSound;
public AudioClip rocketSound;
public Vector3 aa = new Vector3(1,1,1);
private Animator animator;
private PlayerController controller;
void Start(){
controller = GetComponent<PlayerController> ();
animator = GetComponent<Animator> ();
}
void PlayLeftFootSound(){
if (leftFootSound)
AudioSource.PlayClipAtPoint (leftFootSound, transform.position);
}
void PlayRightFootSound(){
if (rightFootSound)
AudioSource.PlayClipAtPoint (rightFootSound, transform.position);
}
void PlayRocketSound(){
if (!rocketSound || GameObject.Find ("RocketSound"))
return;
GameObject go = new GameObject ("RocketSound");
AudioSource aSrc = go.AddComponent<AudioSource> ();
aSrc.clip = rocketSound;
aSrc.volume = 0.7f;
aSrc.Play ();
Destroy (go, rocketSound.length);
}
void OnCollisionEnter2D(Collision2D target){
if (!standing) {
var absVelX = Mathf.Abs(rigidbody2D.velocity.x);
var absVelY = Mathf.Abs(rigidbody2D.velocity.y);
if(absVelX <= .1f || absVelY <= .1f){
if(thudSound)
AudioSource.PlayClipAtPoint(thudSound, transform.position);
}
}
}
// Update is called once per frame
void Update () {
var forceX = 0f;
var forceY = 0f;
var absVelX = Mathf.Abs (rigidbody2D.velocity.x);
var absVelY = Mathf.Abs (rigidbody2D.velocity.y);
if (absVelY < .2f)
standing = true;
else
standing = false;
if (controller.moving.x != 0) {
if (absVelX < maxVelocity.x) {
forceX = standing ? speed * controller.moving.x : (speed * controller.moving.x * airSpeedMultiplier);
aa = transform.localScale = new Vector3 (forceX > 0 ? 1 : -1, 1, 1);
}
animator.SetInteger ("AnimState", 1);
} else {
animator.SetInteger ("AnimState", 0);
}
if (controller.moving.y > 0) {
PlayRocketSound();
if (absVelY < maxVelocity.y)
forceY = jetSpeed * controller.moving.y;
animator.SetInteger ("AnimState", 2);
} else if (absVelY > 0) {
animator.SetInteger("AnimState", 3);
}
rigidbody2D.AddForce (new Vector2 (forceX, forceY));
}
}
3rd Script (PlayerController)
public class PlayerController : MonoBehaviour {
public Vector2 moving = new Vector2();
public int Bulletlimit = 0;
public int MaxBulletlimit = 3;
public float bulletDelay = 3f;
public bool Gun;
public Bullet bullet;
// Use this for initialization
void Start () {}
// Update is called once per frame
void Update () {
moving.x = moving.y = 0;
if (Input.GetKey ("right")) {
moving.x = 1;
} else if (Input.GetKey ("left")) {
moving.x = -1;
}
if (Input.GetKey ("up")) {
moving.y = 1;
} else if (Input.GetKey ("down")) {
moving.y = -1;
}
if (Input.GetKey ("s")) {
if(Gun){
if(Bulletlimit < MaxBulletlimit)
{
Bullet clone = Instantiate (bullet, transform.position, Quaternion.identity) as Bullet;
Bulletlimit = Bulletlimit + 1;
}
}
}
}
public void BulletCount() {
Bulletlimit = Bulletlimit - 1;
}
}
1) There is an easy method to know where to position your bullets and which direction to shoot. Add a child dummy gameobject under your character that will be used as bullet's initial position. Position it where you want. Now this gameobject moves and rotates relative to your character. Use it's transform.position and transform.rotation.forward when you instantiate bullets.
2) Keep current time when user fired a bullet in a variable like private float lastShotTime;. Update it's value when you fired a bullet lastShotTime = Time.time. Then when user wants to shoot another bullet, check if enough time has passed since last shot if (Time.time > lastShotTime + fireDelay) { Shoot(); }.

Categories