Проблемы с Unity Ragdoll Character Creator, массивами Rigidbody [] и общие проблемы с кодом - PullRequest
0 голосов
/ 11 мая 2018

TL; DR: Почему я могу только "убить" своего первого врага, но мои попытки отключить их компоненты не влияют на остальных?

Обзор

Привет, ребята и Галс, у меня возникают проблемы с переключением моего ИИ на Ragdoll, когда игрок убивает их, но, точнее, он не деактивирует другие компоненты.

По сути, у меня есть сценарий ИИкоторый запускает машину состояний с помощью IEnumerators и сопрограмм, у меня также есть сценарий RagdollDeath, чтобы сохранить отдельный код.

В идеале, когда игрок стреляет по врагу, он переключается в состояние тряпичной куклы.

Как мне этого добиться

Помимо отключения всех аниматоров, навигационной сетки и других компонентов, когда здоровье достигает 0, я также отключаю ВСЕ твердые тела, используя

void IsKinematic(bool newvalue)
{
    foreach (Rigidbody rb in bodyparts)
    {
        rb.isKinematic = newvalue;
    }
}

thisсоздает красивый и плавный переход ragdoll из анимации.

My Issue

Проблема, с которой я сталкиваюсь, заключается в том, что, когда я стреляю по врагу, они делают точнокак ожидается, но когда я стреляю в другого врага, он вообще не запускает мой скрипт, хотя я вижу, что он запускается с помощью команд Print («Something»).Я позаботился о том, чтобы заранее приготовить своего врага и применить изменения к указанному сборному.

Что еще более странно, так это то, что если я клонирую 2 врагов и стреляю в нового, то первый из них перешагнет через уровень!Это почти как если бы монобихевиоризм не работал.

Любое понимание того, что может быть причиной этого, будет высоко оценено.

Полный код, вызывающий проблемы
открытый класс ZombieStateMachine: MonoBehaviour {

[SerializeField] GameObject player;
[SerializeField] GameObject los;
[SerializeField] GameObject[] waypoints;
[SerializeField] int timeBetweenWaypoints = 1;
[SerializeField] AudioSource jumpyscare;

private int health = 100;
private SuspenseAudioScript suspensescript;
private NavMeshAgent agent;
public bool canSeePlayer;
public float distanceBetween;
public string routine = "null";
private Animator animator;
public bool isAttacking = false;
private ShootScript shootscript;
private Rigidbody[] bodyparts;
private CapsuleCollider capsule;



void IsKinematic(bool newvalue)
{
    foreach (Rigidbody rb in bodyparts)
    {
        rb.isKinematic = newvalue;
    }
}

// Use this for initialization
void Start () {
    shootscript = GameObject.FindGameObjectWithTag("Player").GetComponent<ShootScript>();
    suspensescript = GetComponent<SuspenseAudioScript>();
    animator = GetComponent<Animator>();
    agent = GetComponent<NavMeshAgent>();
    StartCoroutine(Eyesite());
    StartCoroutine(Wander());
    bodyparts = GetComponentsInChildren<Rigidbody>();
    capsule = GetComponent<CapsuleCollider>();
    IsKinematic(true);

}



public void KillZombie()
{
    this.StopAllCoroutines();
    IsKinematic(false);
    animator.enabled = false;
    agent.enabled = false;
    capsule.enabled = false;
    this.enabled = false;
}



Вот сопровождающий снимокскрипт

public class ShootScript : MonoBehaviour {

[SerializeField] public int health = 100;
[SerializeField] AudioSource gunshotsound;
[SerializeField] Light gunshotflash;


public float impactforce = 2f;
private ZombieStateMachine enemyscript;
private Rigidbody rb;
private CharacterController m_CharacterController;
private Camera cam;
private CapsuleCollider enemycol;
public UnityStandardAssets.Characters.FirstPerson.FirstPersonController fpscontrol;


// Use this for initialization
void Start () {
    fpscontrol = GetComponent<UnityStandardAssets.Characters.FirstPerson.FirstPersonController>();
    enemycol = GameObject.FindGameObjectWithTag("Enemy").GetComponent<CapsuleCollider>();
    enemyscript = GameObject.FindGameObjectWithTag("Enemy").GetComponent<ZombieStateMachine>();
    cam = GetComponentInChildren<Camera>();
    rb = GetComponent<Rigidbody>();
    m_CharacterController = GetComponent<CharacterController>();

}

// Update is called once per frame
void Update () {
    Shoot();
}

public void Shoot()
{
    if (Input.GetKeyDown(KeyCode.Mouse0))
    {
        Debug.DrawRay(cam.transform.position, cam.transform.forward, Color.red, 1.0f);
        RaycastHit hit;
        if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, 2000f))
        {
            if(hit.transform.tag == "Enemy")
            {
                enemyscript.KillZombie();
                gunshotsound.Play();
                StartCoroutine(GunshotFlash());
            }
            else
            {
                gunshotsound.Play();
                StartCoroutine(GunshotFlash());
                print("You MIssed!");
            }
        }
    }
}

IEnumerator GunshotFlash()
{
    while (true)
    {
        gunshotflash.enabled = true;
        yield return new WaitForSeconds(0.05f);
        gunshotflash.enabled = false;
        yield return new WaitForSeconds(1);
        break;
    }
}

public void PlayerDeath()
{
        rb.AddForce(this.transform.forward * 2);
        rb.isKinematic = false;
        m_CharacterController.enabled = false;
        fpscontrol.enabled = false;
        //rb.useGravity = true;
}

}

1 Ответ

0 голосов
/ 05 ноября 2018

Не уверен, что вы когда-нибудь сталкивались с решением этой проблемы, но я полагаю, что проблема в вашем методе запуска сценария Shoot.

enemycol = GameObject.FindGameObjectWithTag("Enemy").GetComponent<CapsuleCollider>();

Выполнение этого вернет первый игровой объект с тегом «Враг», было бы лучше просто сделать:

enemycol = GetComponent<CapsuleCollider>();

Вероятно, то же самое нужно сделать со строкой прямо под ней, переменной врагаскрипта:

enemyscript = GameObject.FindGameObjectWithTag("Enemy").GetComponent<ZombieStateMachine>();

изменить на

    enemyscript = GetComponent<ZombieStateMachine>();
...