I'm making a game in Unity 4.3 with 2D mode. But for some reason the void Start() function isn't being called on the start of the scene. I even attached a Debug.Log("Hello"); to the start function but it doesn't even do that so I know that the Start() function isn't being called. Although, the Update() function is called.
Here is the script.
private void Start()
{
this.animation.Stop();
Debug.Log("Hello");
}
You can see, there is an Update method which does work.
EDIT: Whole script:
public class Player : MonoBehaviour
{
public Vector2 jumpForce = new Vector2(0, 300);
public Vector2 moveForce = new Vector2(0, 300);
public Vector2 sideForce = new Vector2 (250, 0);
public GameObject obstacle;
public float scrollSpeed = 30;
public AnimationClip fly;
public GameObject player;
private float speed = 10.0f;
private void Start()
{
Debug.Log("hi!");
this.animation.Stop();
Debug.Log("Hello");
}
private void Update() {
onTouch();
int fingerCount = 0;
foreach (Touch touch in Input.touches) {
if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
fingerCount++;
}
/*if (fingerCount > 0)
{
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}*/
try
{
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}
catch(UnityException e)
{
Debug.Log("Fail");
}
if (Input.GetKeyDown ("right"))
{
player.rigidbody2D.velocity = Vector2.right;
player.rigidbody2D.AddForce (sideForce);
}
accelorometer();
}
// Die by collision
private void OnCollisionEnter2D(Collision2D other)
{
Die();
}
private void Die()
{
Application.LoadLevel(Application.loadedLevel);
}
private void accelorometer()
{
// Get the accelerometer data:
Vector2 acceleration = Input.acceleration;
// Get the forward value from one of the three channels in the acceleration data:
float translation = acceleration.x * speed;
// Make it move 10 meters per second instead of 10 meters per frame
translation *= Time.deltaTime;
// Move translation along the object's z-axis
player.transform.Translate (translation, 0, 0);
}
private void onTouch()
{
/*int fingerCount = 0;
foreach (Touch touch in Input.touches) {
if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
fingerCount++;
}
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce (moveForce);
}
if (fingerCount > 0)
{
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}*/
if(Input.GetKeyDown ("up"))
{
Debug.Log("ghjkl");
player.rigidbody2D.velocity = Vector2.zero;
player.rigidbody2D.AddForce (moveForce);
}
//print("User has " + fingerCount + " finger(s) touching the screen");
}
You just copy the contents of that script and delete it. then create a new script with same code and attach it to the gameObject. It will resolve the issue.
I've been struggling with this also. I've managed to solve it by changing Logging* to Full in the bottom of Player Settings/Other Settings
Related
I have a problem with an enemy on Unity2D.
The enemy should run to the player and if it's in the attackRange then it has to attack the enemy with a bullet, but the enemy follows my Player.
But there is a problem:
The enemy doesn't shoot with the bullet.
I changed the code, so when I press a button the enemy attacks too.
It worked only with the button.
Here's my code for the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class Enemy2 : MonoBehaviour
{
public Transform target;
public Transform firePoint;
public float speed = 200f;
public float nextWaypointDistance = 3f;
public float range = 10f; // the range at which the enemy will start moving towards the player
public float attackRange = 8f; // the range at which the enemy will attack the player
float distance;
public Transform enemyGFX;
private Transform player; // reference to the player's transform
public GameObject EnemyWeapon;
Path path;
int currentWaypoint = 0;
bool reachedEndOfPath = false;
Seeker seeker;
Rigidbody2D rb;
public Animator animator;
bool Stop = false;
public static float Enemy2Direction;
// Start is called before the first frame update
void Start()
{
seeker = GetComponent<Seeker>();
rb = GetComponent<Rigidbody2D>();
animator = GetComponentInChildren<Animator>();
player = GameObject.FindGameObjectWithTag("Player").transform;
InvokeRepeating("UpdatePath", 0f, .5f);
}
void UpdatePath()
{
if (seeker.IsDone())
{
seeker.StartPath(rb.position, target.position, OnPathComplete);
}
}
void OnPathComplete (Path p)
{
if (!p.error)
{
path = p;
currentWaypoint = 0;
}
}
// Update is called once per frame
void FixedUpdate()
{
if (Pause.IsPause == false)
{
if (path == null)
{
return;
}
if (currentWaypoint >= path.vectorPath.Count)
{
reachedEndOfPath = true;
return;
}
else
{
reachedEndOfPath = false;
}
Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] -rb.position).normalized;
Vector2 force = direction * speed * Time.deltaTime;
rb.AddForce(force);
float distance = Vector2.Distance(rb.position, path.vectorPath[currentWaypoint]);
if (distance < nextWaypointDistance)
{
currentWaypoint++;
}
//You can make look it differently, if you delete 'rb.velocity' and add 'force' instead.
if (rb.velocity.x >= 0.01f)
{
enemyGFX.transform.localScale = new Vector3(-1f, 1f, 1f);
Enemy2Direction = 1f;
}
else if (rb.velocity.x <= -0.01f)
{
enemyGFX.transform.localScale = new Vector3(1f, 1f, 1f);
Enemy2Direction = 0f;
}
if (distance < attackRange)
{
if (Stop = false)
{
StartCoroutine(Attack());
}
}
}
distance = Vector2.Distance(transform.position, player.position);
if (distance > range)
{
Destroy(gameObject);
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
animator.SetBool("Damage", true);
}
if (collision.gameObject.tag == "Bullet")
{
animator.SetBool("Damage", true);
}
}
void Update()
{
if (animator.GetBool("Damage"))
{
StartCoroutine(DamageAnimation());
}
if (Input.GetKeyDown(KeyCode.L))
{
StartCoroutine(Attack());
}
}
IEnumerator Attack()
{
Debug.Log("Attacked");
Stop = true;
yield return new WaitForSeconds(2.0f);
animator.SetBool("Attack", true);
Instantiate(EnemyWeapon, firePoint.position, firePoint.rotation);
yield return new WaitForSeconds(2.0f);
animator.SetBool("Attack", false);
StartCoroutine(Wait());
}
IEnumerator DamageAnimation()
{
yield return new WaitForSeconds(2.0f);
animator.SetBool("Damage", false);
}
IEnumerator Wait()
{
yield return new WaitForSeconds(2.0f);
Stop = false;
}
}
I don't know what's wrong with my code.
Can somebody please help me?
if(Stop == false)
Replace the = in when you check the Stop bool with ==, in C# you use == in order to check for equality
See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators for more detail.
For whatever reason, my player movement stutters every second or every other second, and I'm sure it's to do with my player movement code being in the wrong update method.
Here's my player movement code
[SerializeField] private LayerMask groundLayerMask;
public float speed;
public float Jump;
public sword swordScript;
public GameObject swordSprite;
private float move;
private Rigidbody2D rb;
private BoxCollider2D boxCollider2d;
private bool facingRight;
public SpriteRenderer spr;
public Animator PlayerAnims;
public bool movementAllowed;
public float knockback;
void Awake()
{
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Start is called before the first frame update
void Start()
{
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void FixedUpdate()
{
if(movementAllowed == true)
{
rb.velocity = new Vector2(move * speed, rb.velocity.y);
move = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (isGrounded() && Input.GetButtonDown("Jump"))
{
rb.AddForce(new Vector2(rb.velocity.x, Jump));
}
}
}
void Update()
{
if (movementAllowed == true)
{
Flip(move);
if (move == 0)
{
PlayerAnims.SetBool("isRunning", false);
}
else
{
PlayerAnims.SetBool("isRunning", true);
}
}
}
private bool isGrounded()
{
float extraHeightText = .1f;
RaycastHit2D raycasthit2d = Physics2D.BoxCast(boxCollider2d.bounds.center, boxCollider2d.bounds.size, 0f, Vector2.down, extraHeightText, groundLayerMask);
Color rayColour;
if (raycasthit2d.collider != null)
{
rayColour = Color.green;
PlayerAnims.SetBool("isJumping", false);
}
else
{
rayColour = Color.red;
PlayerAnims.SetBool("isJumping", true);
}
Debug.DrawRay(boxCollider2d.bounds.center + new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, boxCollider2d.bounds.extents.y + extraHeightText), Vector2.right * (boxCollider2d.bounds.extents.x), rayColour);
return raycasthit2d.collider != null;
}
private void Flip(float move)
{
if (move > 0 && !facingRight || move < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
if (swordScript.isFollowing == true)
{
Vector3 swordScale = swordSprite.transform.localScale;
swordScale.x *= -1;
swordSprite.transform.localScale = swordScale;
}
}
}
I tried out your script and I think I barely see that stutter, but one thing seems to fix it.
You have this particular line twice in the code for no reason
rb.velocity = new Vector2(move * speed, rb.velocity.y);
Just remove the first one.
As a rule of thumb:
Calling rb.AddForce: This interacts with Physics - place it in FixedUpdate
Setting rb.velocity: This only sets a value. You are not triggering physics interactions with this - place it in Update
So, at first you should move your code which sets the velocity to the Update function. Also you are setting the velocity twice. Just remove the first line.
As an example here ist the Update and FixedUpdate function:
void FixedUpdate()
{
if(movementAllowed == true)
{
if (isGrounded() && Input.GetButtonDown("Jump"))
{
rb.AddForce(new Vector2(rb.velocity.x, Jump));
}
}
}
void Update()
{
if (movementAllowed == true)
{
float move = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(move * speed, rb.velocity.y);
Flip(move);
if (move == 0)
{
PlayerAnims.SetBool("isRunning", false);
}
else
{
PlayerAnims.SetBool("isRunning", true);
}
}
}
Since you are not using move anywhere else than Update you can just declare it as a local variable and remove the private float move; at the top of the script.
Last thing which should be mentioned:
You are getting component references both in Start or Awake. Generally you should get your references in Start and only get them in Awake when needed.
I'm trying to find a way to rotate the enemy towards the player. Currently it follows/stops and shoots the player. Have not figured out how to make it rotate. Please help if you can. I've tried couple of different things on here but they dont seem to work.
I've tried creating a Flip function with isFacingRight.
private bool facingRight;
public float speed;
public float stoppingDistance;
public float retreatDistance;
private Animator enemyAnimation;
private bool isDead;
private float direction;
public static bool enemyShoot = false;
private float timeBtwShots;
public float startTimeBtwShots;
public GameObject projectile;
private Transform player;
[SerializeField]
private Stat health;
private void Awake()
{
health.Initialize();
}
// Start is called before the first frame update
void Start()
{
//Player tag
player = GameObject.FindGameObjectWithTag("Player").transform;
enemyAnimation = GetComponent<Animator>();
isDead = false;
}
// Update is called once per frame
void Update()
{
if (Vector2.Distance(transform.position, player.position) > stoppingDistance)
{
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
timeBtwShots = startTimeBtwShots;
if(player.position.x > transform.position.x && !facingRight) //if the target is to the right of enemy and the enemy is not facing right
Flip();
if(player.position.x < transform.position.x && facingRight)
Flip();
}
else if (Vector2.Distance(transform.position,player.position) <= stoppingDistance && Vector2.Distance(transform.position,player.position)>retreatDistance)
{
transform.position = this.transform.position;
}
else if (Vector2.Distance(transform.position, player.position) > retreatDistance)
{
transform.localScale = new Vector2(-1f, 1f);
transform.position = Vector2.MoveTowards(transform.position, player.position, -speed * Time.deltaTime);
timeBtwShots = 100;
enemyAnimation.SetTrigger("Attack");
}
if (enemyShoot == true)
{
//Stops animation Loop
enemyShoot = false;
enemyAnimation.SetTrigger("Shoot");
}
if (timeBtwShots <= 0)
{
Instantiate(projectile, transform.position, Quaternion.identity);
timeBtwShots = startTimeBtwShots;
}
else
{
timeBtwShots -= Time.deltaTime;
}
if (health.CurrentVal == 0)
{
timeBtwShots = 100;
FindObjectOfType<SoundsScript>().Play("SaibaDeath");
isDead = true;
enemyAnimation.SetBool("Dead", isDead);
Destroy(gameObject, 2f);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "ProjectileEnem")
{
health.CurrentVal -= 50;
enemyAnimation.SetTrigger("Hurt");
}
}
//Disables enemeies when off screen
private void OnBecameInvisible()
{
GetComponent <Enemy> ().enabled = false;
}
//Re enables enemies once they are visible
private void OnBecameVisible()
{
GetComponent<Enemy>().enabled = true;
}
void Flip(){
Vector3 scale = transform.localScale;
scale.x *= -1;
transform.localScale = scale;
facingRight = !facingRight;
}
}
Try this:
spriteRenderer.flipX = transform.position.x < player.position.x;
SpriteRenderer contains the flipX and flipY property, you do not need to create your own Flip() function.
You need a reference to the SpriteRenderer on your GameObject.
The above code is assuming that your sprite faces left on default. If your sprite faces right normally, change the < to >.
i've been having this problem with my 2d sprites (enemies characters in my case) where if I have a prefab already made from one scene that works just fine, and use that prefab in another scene, the size is not the same, but it behaves the same if it runs into a wall or something (it turns the other direction). It's not the script because the movement script is attached to other gameobjects that as of now behave the same way and those prefabs get imported to other scenes just fine. Does anyone know if this is a Unity bug or something? It's not a script issue I'm sure. In fact I know it isn't because it's happened with other enemies with different scripts. Sometimes this issue only happens in one scene, sometimes several, sometimes all of them, as long as it's not the original scene the game object and prefab was created in.
I should also mention that when I build the actual game, the game objects work as they should. It's only when I'm in the unity program itself that this is happening. But I can't properly test some scenes unless I were to build the game scene over and over which would be very counterproductive.
here's the script attached to the enemy for those insistent.
using UnityEngine;
using System.Collections;
public class foeHP : MonoBehaviour {
public GameObject deathFlamePrefab;
Rigidbody2D erb;
public float Walk= 2.5f;
private float idle = 0f;
public float move = 2.5f;
public float hp = 3f;
private slicer slicy;
Animator anim;
private bool alive = true;
private bool damager = false;
private float invuln = 0f;
private bool nothurt = true;
public float wallCheckRadius;
public LayerMask whatIsWall;
private bool wallHit;
private bool goRight;
private bool atEdge = false;
public bool spotted;
public float xScale;
public float yScale;
public Transform wallCheck;
public Transform edgeCheck;
public GameObject bonePrefab;
public Transform boneSpawn;
public float fireDelay = 0.5f;
public float coolDownTimer = 0f;
public float timer3 = 0.75f;
private bool damagePlayed = false;
void Start ()
{
anim = GetComponent<Animator>();
erb = GetComponent<Rigidbody2D> ();
}
void Update ()
{
invuln -= Time.deltaTime;
Recover ();
HandleMovement ();
notHurting ();
// Born ();
damagePlayed = false;
}
public void takeDamage (float amount)
{
hp -= amount;
damager = true;
if (!damagePlayed && alive && hp <= 0)
{
Instantiate (deathFlamePrefab, transform.position, transform.rotation);
Destroy (gameObject);
}
if (alive && hp > 0) {
anim.SetTrigger ("damaged");
invuln = 0.5f;
gameObject.layer = 14;
Invoke ("layerReturn", timer3);
}
if (alive && hp > 0 && !damagePlayed) {
soundManager.PlaySFX ("enemyHit");
damagePlayed = true;
}
}
void layerReturn()
{
gameObject.layer = 12;
}
public void HandleMovement()
{
if (wallCheck == null) {
return;
} else {
wallHit = Physics2D.OverlapCircle (wallCheck.position, wallCheckRadius, whatIsWall);
atEdge = Physics2D.OverlapCircle (edgeCheck.position, wallCheckRadius, whatIsWall);
if (wallHit || !atEdge)
goRight = !goRight;
if (goRight) {
transform.localScale = new Vector3 (-xScale, yScale, 1f);
erb.velocity = new Vector2 (move, erb.velocity.y);
anim.SetFloat ("walk", Mathf.Abs (move));
} else {
transform.localScale = new Vector3 (xScale, yScale, 1f);
erb.velocity = new Vector2 (-move, erb.velocity.y);
anim.SetFloat ("walk", Mathf.Abs (move));
}
}
Physics2D.IgnoreLayerCollision (12, 12);
}
public void Recover ()
{
if (invuln <= 0)
gameObject.layer = 12;
nothurt = false;
if (invuln <= 0)
anim.SetLayerWeight (1, 0);
nothurt = true;
}
public void notHurting()
{
if (invuln > 0)
erb.velocity = Vector2.zero;
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Player")
spotted = true;
else
spotted = false;
}
/* void Born ()
{
coolDownTimer -= Time.deltaTime;
if (spotted && coolDownTimer <= 0)
{
coolDownTimer = fireDelay;
anim.SetTrigger ("Throw");
Instantiate (bonePrefab, boneSpawn.position, boneSpawn.rotation);
if (!spotted)
fireDelay = 0;
}
}
*/
}
I've got the following player controller:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
[RequireComponent(typeof(NetworkIdentity))]
public class PlayerController : NetworkBehaviour {
public Vector3 size = new Vector3(1, 1, 1);
public float speed = 10;
public float rotateSpeed = 9;
private Transform _transform;
private Map _map;
private BoxCollider _collider;
private bool _active = false;
private Vector3 _lastPosition;
private bool _isGrounded = false;
void Start () {
_transform = transform;
Messenger.AddListener ("MAP_LOADED", OnMapLoaded);
_transform.localPosition = new Vector3 (-100, -100, -100);
gameObject.name = "Player " + gameObject.GetComponent<NetworkIdentity> ().netId.Value;
_collider = gameObject.GetComponent<BoxCollider> ();
_map = GameObject.Find ("Map").GetComponent<Map> ();
_collider.size = size;
}
void OnMapLoaded () {
if (isLocalPlayer) {
// Hook up the camera
PlayerCamera cam = Camera.main.GetComponent<PlayerCamera>();
cam.target = transform;
// Move the player to the it's spawn location
_transform.localPosition = _map.GetPlayerSpawn();
}
// Set the player as active
_active = true;
}
void Update () {
if (!isLocalPlayer || !_active) {
return;
}
_lastPosition = _transform.position;
float transAmount = speed * Time.deltaTime;
float rotateAmount = rotateSpeed * Time.deltaTime;
if (Input.GetKey ("up")) {
transform.Translate (0, 0, transAmount);
}
if (Input.GetKey ("down")) {
transform.Translate (0, 0, -transAmount);
}
if (Input.GetKey ("left")) {
transform.Rotate (0, -rotateAmount, 0);
}
if (Input.GetKey ("right")) {
transform.Rotate (0, rotateAmount, 0);
}
if (!_isGrounded) {
Vector3 down = _transform.TransformDirection(Vector3.down);
_transform.position += down * Time.deltaTime * _map.gravity;
}
}
void FixedUpdate () {
//
// Check what is below us
//
Vector3 down = _transform.TransformDirection(Vector3.down);
RaycastHit[] hits;
hits = Physics.RaycastAll(_transform.position, down, size.y + 0.001f);
_isGrounded = false;
foreach (RaycastHit hit in hits) {
if (hit.collider.gameObject.tag.ToUpper() == "GROUND") {
_isGrounded = true;
}
}
}
void OnTriggerEnter(Collider collider) {
Debug.Log ("Triggered by " + collider.gameObject.tag.ToUpper ());
if (collider.gameObject.tag.ToUpper () == "GROUND") {
transform.position = _lastPosition;
}
}
}
In Update I'm taking the user's input and moving the transform around. In FixedUpdate I'm checking to see if the player is on the ground and setting a flag appropriately. And finally in OnTriggerEnter I'm checking to see if I'm trying to go through anything.
If in OnTriggerEnter I hit something I try to set the player's position back to a good one, but that's not happening. My guess is because _lastPosition isn't what I'm expecting it to be.
Is there a better way to do this?
Use rigidbody.Move(position) instead of transform.Translate(position).
Note: Using transform.translate causing performance issues and you must handle collision detection manually.