Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by Catralitos · Mar 12, 2018 at 07:05 PM · 2d-platformershootingtranslateinstantiation

Creating a MegaMan style game, writing bullet script, need help moving it across screen.

So I'm creating a Mega Man style game, which will have the regular Mega Buster (standard bullet) and later on 8 unique weapons. As such, on my PlayerController script I have:

 public GameObject[] weapons = new GameObject[9];

,at the beginning. I then have a method:

 int ChooseWeapon ()
     {
         return 0;
     }

which currenly returns 0, because the only weapon in the game is that standard one that shoots a bullet. (I'll later program a way to choose a different one). Then I have the following method to shoot.

 void Shoot (int weapon)
     {
         if (Input.GetButtonDown ("Fire1")) {
             Instantiate (weapons [weapon], new Vector2 (trans.position.x, trans.position.y), Quaternion.identity);
         }
 
     }

,with trans being a transform. (Also need to spawn it a bit in front of the player, not right on top, but I'll fix that later) Now I need help with the script that's gonna be attached to the bullet prefab.

 public float bulletSpeed;
 
     public Transform trans;
 
     void Start () 
     {
         trans = GetComponent<Transform> ();
     }
     
     void Update () 
     {
         trans.Translate (/*player x*/ * bulletSpeed, /*player y*/, 0);        
     }

What's the best way to get the player's position, or to say it's traveling from the starting position where it's instantiated.

Feel free to ask for more code, tough there isn't much and thanks for the help in advance.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Catralitos · Mar 13, 2018 at 06:01 PM

@SeigneurNecron Seems to work mostly fine, but the bullets still will only shoot in one direction.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 
 public class PlayerController : MonoBehaviour
 {
 
 
     public float jumpLimit;
     public float jumpPower;
     public float speed;
     public float step;
     public float fireRate;
     public float nextFire;
     public float bulletSpeed;
 
     private bool facingRight = true;
     private bool isOnGround = true;
 
     private const float BULLET_SPAWN_OFFSET = 0.5f;
 
     public Animator anim;
     public GameObject[] weapons = new GameObject[9];
     public Rigidbody2D rb;
     public Transform trans;
 
     public bool FacingRight {
         get;
         private set;
     }
 
     void Awake ()
     {
         anim = GetComponent<Animator> ();
         rb = GetComponent<Rigidbody2D> ();
         trans = GetComponent<Transform> ();
     }
 
     void Update ()
     {
         MovePlayer ();
         Jump ();
         Shoot (ChooseWeapon ());
     }
 
     void MovePlayer ()
     {
         float translate = Input.GetAxisRaw ("Horizontal") * speed * Time.deltaTime;
         trans.Translate (translate, 0, 0);
         if (translate > 0) {
             anim.SetTrigger ("PlayerRunRight");
             if (!facingRight)
                 Flip ();
         }
         if (translate < 0) {
             anim.SetTrigger ("PlayerRunLeft");
             if (facingRight)
                 Flip ();
         }
         if (translate == 0)
             anim.SetTrigger ("PlayerStop");
     }
 
     void Jump ()
     {
         if (Input.GetButtonDown ("Jump") && isOnGround) {
             rb.AddForce (new Vector2 (0, jumpPower), ForceMode2D.Impulse);
         }            
     }
 
     void Flip ()
     {
         facingRight = !facingRight;
         Vector3 theScale = transform.localScale;
         theScale.x *= -1;
         transform.localScale = theScale;
     }

//both of these are wrong I know, but I'm a newbie, this can //be saved for later, just testing out character controll on a flat //surface for now

     void OnCollisionEnter2D ()
     {
         isOnGround = true;
     }
 
     void OnCollisionExit2D ()
     {
         isOnGround = false;
     }
 
     int ChooseWeapon ()
     {
         return 0;
     }
 
     void Shoot (int weapon)
     {
         if (Input.GetButtonDown ("Fire1")) {
             Vector3 spawnLocation = this.transform.position + new Vector3(BULLET_SPAWN_OFFSET * (this.facingRight ? -1 : 1), 0f, 0f);
             MegaBusterBullet bullet = Instantiate(this.weapons[this.ChooseWeapon()], spawnLocation, Quaternion.identity).GetComponent<MegaBusterBullet>();
             bullet.FacingRight = this.FacingRight;
         }
 
     }
 }

With the bullet script being

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class MegaBusterBullet : MonoBehaviour {
 
     public float bulletSpeed;
     private Rigidbody2D rigidBody;
 
     public bool FacingRight {
         get;
         set;
     }
 
     public float MoveSpeed {
         get 
         {
             return this.bulletSpeed * (this.FacingRight ? -1 : 1) * Time.deltaTime;
         }
     }
 
     private void Awake() {
         this.rigidBody = this.GetComponent<Rigidbody2D>();
     }
 
     private void FixedUpdate() {
         this.rigidBody.MovePosition(this.transform.position + new Vector3(this.MoveSpeed, 0f, 0f));
     }
 
 }

Currently no matter what direction I'm turned to (I'm flipping my character well, so facingRight must be working) I'm shooting my bullets to the right. Can't shoot left.

Comment
Add comment · Show 18 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Catralitos · Mar 13, 2018 at 07:34 PM 0
Share

$$anonymous$$y theory is that the getter might be wrong. facingRight is changing it's value properly in Flip(), so for the bullets to go only in one direction, they must not be getting facingRight properly.

avatar image SeigneurNecron Catralitos · Mar 13, 2018 at 07:45 PM 1
Share

In fact, writing this :

         public bool FacingRight {
             get;
             private set;
         }

is equivalent to :

         private bool fieldThatYouCantAccessDirectly = false;
 
         public bool FacingRight {
             get {
                 return this.fieldThatYouCantAccessDirectly;
             }
             private set {
                 this.fieldThatYouCantAccessDirectly = value;
             }
         }

Hence, in this case FacingRight has nothing to do with facingRight. This is called an Auto Property.

avatar image Catralitos Catralitos · Mar 13, 2018 at 07:46 PM 0
Share
 public bool FacingRight {
         get
         {
             return facingRight;
         }
     }
 
 Changed the getter in the PlayerController to this and it seems to be working (actually the reverse directions, but for that just gotta change where the $$anonymous$$us is).
avatar image SeigneurNecron · Mar 13, 2018 at 07:35 PM 1
Share
  • The problem here is that you are sometimes using the field facingRight and sometimes using the property FacingRight. A good way to avoid doing this kind of mistakes is to only use the field inside the property, and update everything that is affected inside the property.

  • I also noticed you were potentially triggering "PlayerStop" a lot when not needed.

  • You should also replace all instances of (this.FacingRight ? -1 : 1) by (this.FacingRight ? 1 : -1)

    I suggest you to do something like this:

           // $$anonymous$$eep this :
             private bool facingRight = true;
     
             // Add this :
             private bool moving = false;
     
             // $$anonymous$$odifiy this :
             public bool FacingRight {
                 get {
                     return this.facingRight;
                 }
                 private set {
                     if(this.facingRight != value) {
                         this.facingRight = value;
                         anim.SetTrigger(this.facingRight ? "PlayerRunRight" : "PlayerRunLeft");
                         Vector3 theScale = transform.localScale;
                         theScale.x *= -1;
                         transform.localScale = theScale;
                     }
                 }
             }
     
             // Add this :
             public bool $$anonymous$$oving {
                 get {
                     return this.moving;
                 }
                 private set {
                     if(this.moving != value) {
                         this.moving = value;
     
                         if(!this.moving) {
                             anim.SetTrigger("PlayerStop"); // Doing it this way will ensure the trigger only happens when $$anonymous$$oving goes from true to false, ins$$anonymous$$d of happening every frame while the player is not moving.
                         }
                     }
                 }
             }
     
             // $$anonymous$$odifiy this too :
             void $$anonymous$$ovePlayer() {
                 float translate = Input.GetAxisRaw("Horizontal") * speed * Time.deltaTime;
                 transform.Translate(translate, 0, 0);
     
                 if(translate == 0) {
                     this.$$anonymous$$oving = false;
                 }
                 else {
                     this.$$anonymous$$oving = true;
                     this.FacingRight = translate > 0;
                 }
             }
     
             // Remove this :
             void Flip() {
                 facingRight = !facingRight;
                 Vector3 theScale = transform.localScale;
                 theScale.x *= -1;
                 transform.localScale = theScale;
             }
    
    
avatar image Catralitos SeigneurNecron · Mar 13, 2018 at 08:02 PM 0
Share

Seems to work fine, but sometimes the animations just won't play, and there's a tiny recoil when you shoot a bullet, that I'm not really a fan of. I don't really know why sometimes the animations play and sometimes don't seems kinda random.

avatar image SeigneurNecron Catralitos · Mar 13, 2018 at 10:39 PM 1
Share

Weird... I don't see how this modifications can cause a recoil. For the animations that don't always play, it's hard to tell without seeing the animator transitions.

Show more comments
avatar image
1

Answer by SeigneurNecron · Mar 12, 2018 at 11:46 PM

  • Don't use Update(), it's frame rate dependent, use the physic update FixedUpdate()instead.

  • Multiply your bullet speed by Time.deltaTime to convert from distance/second to distance/update.

  • Don't use the player position when updating the bullet position, the player and bullet will move independently, use the current bullet transform.position instead.

  • You don't need to use GetComponent<Transform>(), the transform is always available in the transform field of any class extending Component.

  • You also need to know if the bullet is going to the left or the right, you can store that in a public boolean property Direction for example, so can set it from you player script, and it won't appear in the inspector.

  • You should not update the bullet transform position directly, but use Rigidbody2D.MovePosition() instead, so the collisions are handled properly. You will need to attach a RigidBody2D component to your bullet prefab (Body Type: Kinematic) and store it in a field like you did for the transform. (There is a rigidbody field but it's deprecated). That field should be private, you don't need to modify its value from outside of the bullet script.

    So the bullet script should look like this:

         public class MegaBusterBullet : MonoBehaviour {
     
             public float bulletSpeed;
             private Rigidbody2D rigidBody;
     
             public bool Direction {
                 get;
                 set;
             }
     
             public float MoveSpeed {
                 get {
                     return this.bulletSpeed * (this.Direction ? -1 : 1) * Time.deltaTime;
                 }
             }
     
             private void Awake() {
                 this.rigidBody = this.GetComponent<Rigidbody2D>();
             }
     
             private void FixedUpdate() {
                 this.rigidBody.MovePosition(this.transform.position + new Vector3(this.MoveSpeed, 0f, 0f));
             }
     
         }
    
    



  • When you instantiate your bullet in your player script, don't forget to set its direction to be the same as the player's current direction.

    The player script should look like this:

       public class Player : MonoBehaviour {
     
             private const float BULLET_SPAWN_OFFSET = 0.5f;
     
             [SerializeField]
             private GameObject[] weapons = new GameObject[9];
     
             public bool Direction {
                 get;
                 private set;
             }
     
             public int EquipedWeapon {
                 get;
                 private set;
             }
     
             private void Update() {
                 if(Input.GetButtonDown("Fire1")) {
                     this.Shoot();
                 }
     
                 if(Input.GetButtonDown("SwitchWeapon0")) {
                     this.EquipedWeapon = 0;
                 }
             }
     
             private void Shoot() {
                 Vector3 spawnLocation = this.transform.position + new Vector3(BULLET_SPAWN_OFFSET * (this.Direction ? -1 : 1), 0f, 0f);
                 MegaBusterBullet bullet = Instantiate(this.weapons[this.EquipedWeapon], spawnLocation, Quaternion.identity).GetComponent<MegaBusterBullet>();
                 bullet.Direction = this.Direction;
             }
     
         }
    
    



Hope this helps. :)

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Rygaran · Mar 13, 2018 at 06:52 PM 1
Share

dont use time.deltaTime in fixed update, since deltatime is the time between normal update.

avatar image SeigneurNecron Rygaran · Mar 13, 2018 at 06:55 PM 1
Share

https://docs.unity3d.com/ScriptReference/Time-deltaTime.html

When called from inside $$anonymous$$onoBehaviour's FixedUpdate, returns the fixed framerate delta time

avatar image Catralitos Rygaran · Mar 13, 2018 at 06:58 PM 0
Share

So does that mean I turn the FixedUpdate() in the $$anonymous$$egaBuster script to an Update() or do I touch something else. Because the Time.DeltaTime used in moveSpeed() is the only one that I could say is being used on FixedUpdate(), since the value that returns is used in that update method.

avatar image SeigneurNecron Catralitos · Mar 13, 2018 at 07:03 PM 1
Share

What @Rygaran wanted to say, is that you should use Time.fixedDeltaTime ins$$anonymous$$d of Time.deltaTime. But when called in the FixedUpdate() method, Time.deltaTime returns Time.fixedDeltaTime anyway. So you don't have to touch anything.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

82 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

2D Shooting to target position (same bullet speed regardless of target's and gun's position) 0 Answers

Shooting bullets up (y axis) 0 Answers

How can I make my character shoot? 0 Answers

2 Shooting Questions 1 Answer

Patrolling enemy not shooting at player 2d platformer 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges