简体   繁体   中英

Unity C# script rotation offset

I've been tinkering with this for a while and can't seem to get it to work properly, it sometimes works but other times does not.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class gun: MonoBehaviour
{
    public Transform firePoint;
    public GameObject BulletPrefab;
    
    float Speed = 20f;
    
    void Update()
    {
        if(Input.GetButtonDown("Fire1"))
        {
            Shoot();
        }
    }
    
    void Shoot()
    {
        int a = 0;
        float[] b1 = {-15f,0f,15f};
    
        while (a != 3)
        {
            GameObject bullet = Instantiate(BulletPrefab, firePoint.position, firePoint.rotation);
    
            Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
            Transform tr = bullet.GetComponent<Transform>();
            tr.rotation = firePoint.rotation;
            tr.Rotate(new Vector3(0f,0f,b1[a]),Space.Self);
            rb.AddForce(tr.up * Speed, ForceMode2D.Impulse);
  
            a++;
        }   
    }
}

It's supposed to offset the projectiles at 15 degrees angles and shoot them, but sometimes it just rotates inwards and shoots straight forward.

Tried to convert it to vectors and back but have no clue how to do that and can't seem to find help on this even on page 2 of Google.

I believe that, from the few information that are present, you want to "triple shoot" your bullets from your gun position and make it go forward depending on your gun rotation and rotation offset? If so then here are the problems and solutions to your code:

The problem

I recommend using tr.eulerAngles which uses Vector3 and it's easier to understand and manipulate. With that, you can simply do:

tr.eulerAngles = firePoint.transform.eulerAngles

This will make your bullet copy the gun rotation. Now, if you want to add some rotation to your bullet to make a "triple shot" effect, you would only need to add a Vector3 to modify the y value of your angle. Example:

tr.eulerAngles = firePoint.transform.eulerAngles + new Vector3(0, -15, 0);

This will fix your problem with rotation.

Tips to upgrade your code

Even though this simply line of code will fix your problem, your script has a lot of issues with proper coding and video games basic rules.

First rule of video games, is to never instantiate object during Runtime.
Why? Let's say you shoot 10 bullets at once with a fast firerate, then your game will be very laggy because you are instantiating new objects in your memory (and erasing afterwards). It's a very beginner issue that simply requires the use of Object Pooling .

Another tip is to better name your variables and respect naming conventions. Instead of using 1-2 letter(s) variables use understandable key-words:

tr -> transform
a -> rotationOffset
BulletPrefab -> bulletPrefab
Speed -> speed

You should learn the conventions so your code is more clear for others but also for yourself.

Last tip, if your loop can predict it's end (in this case it's a triple shot so it's from 0 to 3 exclusive) then you should use a for() instead of while() loop.

I highly recommend you to check out some basic coding lessons/tutorials, it will save you from lot of issues in the future.

Some general suggestions here

First make your Inspector exposed field of the correct type right away

public Rigidbody2D bulletPrefab;

this way you ensure the referenced object actually has such a component and don't need GetComponent later.

Then you create an array everytime you shoot.. rather have it persistent

 private static readonly float[] offsets = {-15f,0f,15f};

then usually you would use a proper for loop and iterate over the actual size of the array instead of using a while

for(var i = 0; i < offsets.Length; i++)
{
    ...
}

and finally you shouldn't go through transform at all when using physics but only the Rigidbody2D and do eg

void Shoot()
{

    for(var i = 0; i < offsets.Length; i++)
    {
        var bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation * Quaternion.Euler(0, 0, offsets[i]));
        rb.AddForce(Quaternion.Euler(0, 0, rb.rotation * Vector3.up * Speed, ForceMode2D.Impulse);
    }   
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM