Создание пули в направлении позиции игрока - PullRequest
2 голосов
/ 23 мая 2019

При вводе левой кнопкой мыши (Fire1) снаряд появляется из позиции projectileSpawn. При щелчке правой кнопкой мыши (Fire2) я хочу, чтобы снаряд стрелял «в обратном направлении» и начинался с позиции projectileSpawnTwo и обратно в исходное местоположение projectileSpawn. В настоящее время он стреляет вперед, но я хочу, чтобы снаряд вернулся в точное положение.

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

public class PlayerWeapon : MonoBehaviour 
{
    public GameObject projectilePrefab;

    public GameObject projectileTwoPrefab;

    public Transform projectileSpawn;
    public Transform projectileSpawnTwo;

    public float projectileSpeed = 30;  

    void Update () 
    {
        if (Input.GetButtonDown("Fire1")) 
        {
            Fire();
        }

        if (Input.GetButtonDown("Fire2")) 
        {
            Fire2();
        }
    }

    private void Fire() 
    {
        GameObject projectile = Instantiate(projectilePrefab);

        Physics.IgnoreCollision(projectile.GetComponent<Collider>(),
                                projectileSpawn.parent.GetComponent<Collider>()); 

        projectile.transform.position = projectileSpawn.position;

        var rot = projectile.transform.rotation.eulerAngles;

        projectile.transform.rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);

        projectile.GetComponent<Rigidbody>().AddForce(projectileSpawn.forward * projectileSpeed, ForceMode.Impulse);       
    }

    private void Fire2()
    {
        GameObject projectile = Instantiate(projectileTwoPrefab);

        Physics.IgnoreCollision(projectile.GetComponent<Collider>(),
                                projectileSpawnTwo.parent.GetComponent<Collider>()); 

        projectile.transform.position = projectileSpawnTwo.position;

        var rot = projectile.transform.rotation.eulerAngles;

        projectile.transform.rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);

        projectile.GetComponent<Rigidbody>().AddForce(projectileSpawnTwo.forward * projectileSpeed, ForceMode.Impulse);
    }
}

1 Ответ

2 голосов
/ 23 мая 2019

Поскольку оба метода очень похожи, чтобы немного обобщить ваш метод, вы можете сделать

private Collider projectileSpawnParentCollider;

privtae enum FireType
{
    One,
    Two
}

private void Awake()
{
  // this hould probably done only once to be more efficient
  projectileSpawnParentCollider = projectileSpawn.parent.GetComponent<Collider>();
}

private void Update()
{
    if (Input.GetButtonDown("Fire1")) 
    {
        Fire(FireType.One);
    }

    if (Input.GetButtonDown("Fire2")) 
    {
        Fire(FireType.Two);
    }
}

private void Fire(FireType fireType) 
{
    var position = fireType == FireType.One ? projectileSpawn.position : projectileSpawnTwo.position;

    var rot = projectile.transform.rotation.eulerAngles;

    var rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);

    // pass the position and rotation alraedy
    GameObject projectile = Instantiate(projectilePrefab, position, rotation);

    Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawnParentCollider);


    var forceDirection = fireType == FireType.One ? projectileSpawn.forward : (projectileSpawn.position - projectileSpawnTwo.position).normalized;

    projectile.GetComponent<Rigidbody>().AddForce(forceDirection * projectileSpeed, ForceMode.Impulse);
}

The

projectileSpawn.position - projectileSpawnTwo.position

возвращает Вектор, указывающий от projectileSpawnTwo.position к projectileSpawn.position. Использование normalized возвращает вектор с тем же направлением, но с magnitude = 1.


Однако обратите внимание, что это работает, конечно, только если игрок не двигается после второго броска. Если игрок может двигаться, вам, скорее всего, следует добавить другой компонент, чтобы объект пули действительно следовал позиции игрока.

Вы можете использовать Quaternion.LookRotation и Rigidbody.MoveRotation, чтобы написать отдельный компонент, например,

public class FollowPlayer : MonoBehaviour
{
    public Transform PlayerTransform;
    public RigidBody rigiBody;
    public speed;

    private void Awake()
    {
       rigidBody = GetComponent<RigidBody>();
    }

    private void LateUpdate()
    {
        if(!PlayerTrasnform) return;

        var rotation = Quaternion.LookRotation(PlayerTransform.position - transform.position, Vector3.up);

        rigidBody.MoveRotation(rotation);
        rigidBody.velocity = (PlayerTransform.position - transform.position).normalized * speed;
    }
}

и в вашем скрипте добавьте компонент в случае два как

private void Fire(FireType fireType) 
{
    var position = fireType == FireType.One ? projectileSpawn.position : projectileSpawnTwo.position;

    var rot = projectile.transform.rotation.eulerAngles;

    var rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);

    // pass the position and rotation alraedy
    GameObject projectile = Instantiate(projectilePrefab, position, rotation);

    Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawnParentCollider);

    if(fireType == FireType.One)
    {
        projectile.GetComponent<Rigidbody>().AddForce(projectileSpawn.forward * projectileSpeed, ForceMode.Impulse);
    }
    else
    {
        var follow = projectile.AddComponent<FollowPlayer>();
        follow.speed = projectileSpeed;
        follow.PlayerTransform = YourPlayerTransform; // or probably projectileSpawn
    }
}

Примечание: напечатано на смартфоне, так что никаких гарантий, но я надеюсь, что идея проясняется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...