Jak naprawić te skrypty

0

Cześć otóż robię grę w unity. Planuję bardziej rozbudować tę produkcję ale nie do końca rozumiem C#. Na chwilę obecną potrzebuje pomocy w dopracowaniu systemu Double-Jumpa. Codzi o to że chcę aby po wjechaniu oraz zderzeniu się z Colliderami np jakiejś jakiejś monety uruchamiało to skrypt który doda do postaci umiejętność double-jumpa. Sam skok mam zaprogramowany ale nie wiem jak zmieniać jego wartość innym skryptem żeby właśnie z jednego skoku wartość zmieniała się na dwa skoki. Dorzucam kod do systemu poruszania się oraz do systemu tej monety.

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

public class ogcontrol : MonoBehaviour
{
    public float chodz;
    public float bieganie;
    private float aktual;
    public float mouseSens;
    public float jumpPlayer;
    private Rigidbody rb;
    private int jumpLeft = 2;

    private bool canJump;

    jddsped motor;



    void Start()
    {

        aktual = chodz;
        motor = GetComponent<jddsped>();
        rb = GetComponent<Rigidbody>();
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.LeftShift))
        {

            aktual = bieganie;

        }
        else if (Input.GetKeyUp(KeyCode.LeftShift))
        {
            aktual = chodz;
        }

  
        float _xMove = Input.GetAxisRaw("Horizontal");
        float _zMove = Input.GetAxisRaw("Vertical");
        Vector3 _moveHorizontal = transform.right * _xMove;
        Vector3 _moveVertical = transform.forward * _zMove;

        Vector3 _velocity = (_moveHorizontal + _moveVertical).normalized * aktual;


        motor.Move(_velocity);

        float _yRot = Input.GetAxisRaw("Mouse X");

        Vector3 _rotation = new Vector3(0, _yRot, 0) * mouseSens;



        motor.Rotate(_rotation);

        float _xRot = Input.GetAxisRaw("Mouse Y");

        Vector3 _cameraRotation = new Vector3(_xRot, 0, 0) * mouseSens;


        motor.RotateCamera(_cameraRotation);


        if (Input.GetKeyDown(KeyCode.Space) && jumpLeft > 0)
        {
            rb.AddForce(Vector3.up * jumpPlayer);
            jumpLeft--;
        }

    }

    private void OnCollisionEnter(Collision collision)
    {
 
        jumpLeft = 1;
    }

 


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


public class punkt : MonoBehaviour
{

    void OnTriggerEnter(Collider collison)
    {


        Destroy(gameObject);
       

    }


}

0

Jeśli obiekt z komponentem gracza ogcontrol jest tylko jeden na scenie. To możesz z niego zrobić "Singleton" i raczej będzie to wydajniejsze, niż wywoływanie w triggerze punkt metody GetComponent, co możesz zrobić alternatywnie, żeby się dobrać do obiektu z komponentem ogcontrol.

Żeby zrobić Singleton, dodaj w ciele klasy ogcontrol:

public static ogcontrol instance;

W metodzie Start albo Awake dopisz:

instance = this;

Gotowe ;)

Teraz w klasie punkt, żeby się odnieść do tego obiektu, piszesz:

ogcontrol.instance.DoubleJumpActivate();

Oczywiście musisz zaimplementować taką publiczną metodę.

No i w OnCollisionEnter, jumpLeft zwiększasz o 2 jeślie DoubleJump jest aktywny.

0

@Spine: Okej wygląda dobrze ale co w przypadku jeśli postać może znajdować się na kilku scenach ?

0

To musisz gdzieś zapisywać umiejętności gracza i w każdej scenie na początku musisz ładować to co gracz sobie odblokował.

Jeśli odblokowane umiejętności mają być dostępne w całej sesji gry i nie chcesz zapisywać żadnych danych na dysku, to możesz zrobić jakąś klasę ze zmiennymi statycznymi, które przechowują informacje niezależnie od obiektów załadowanych na scenie. Wtedy Twoja klasa gracza, triggery itp. wpływają na tą klasę statyczną i czytają z niej potrzebne dane w odpowiednich sytuacjach.

0

Ogólnie unikaj statycznych klas i zmiennych - utwórz zwykłą klasę, przeciągnij jej instancję na instancję gracza jako zależność.
Używanie staticów później Cię zablokuje gdybyś chciał stworzyć grę multiplayer albo split-screen - będziesz musiał te wszystkie statiki przepisywać

1

@obscurity: I tak po zmianie sceny i ponownym załadowaniu obiektów, ten obiekt przeciągnięty na instancję gracza wraca do stanu pierwotnego...

Można zrobić zwykłą klasę na przyszłość, którą opisujesz i trzymać ją jako pole statyczne w innej klasie, żeby wszędzie był do tych danych dostęp...

0

@Spine: Odnosząc się do pierwszej odpowiedzi
"Teraz w klasie punkt, żeby się odnieść do tego obiektu, piszesz:

ogcontrol.instance.DoubleJumpActivate();

Oczywiście musisz zaimplementować taką publiczną metodę.

No i w OnCollisionEnter, jumpLeft zwiększasz o 2 jeślie DoubleJump jest aktywny."

Nie do końca rozumiem jak mam to zrobić

0

@Adam Matuszek

  1. W ogcontrol piszesz nową metodę public DoubleJumpActivate() { ... }.
  2. W ogcontrol dodajesz nowe pole bool doubleJump = false;.
  3. W ciele metody DoubleJumpActivate piszesz doubleJump = true;
  4. Twój trigger:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class punkt : MonoBehaviour
{

    void OnTriggerEnter(Collider collison)
    {
        ogcontrol.instance.DoubleJumpActivate();
        Destroy(gameObject);
    }

}
  1. Twój OnCollisionEnter w ogcontrol
    private void OnCollisionEnter(Collision collision)
    {
        if (doubleJump)
        {
                jumpLeft = 2;
        }
        else
        {
                jumpLeft = 1;
        }
    }

Domyślam, się, że TwójjumpLeft się resetuje w OnCollisionEnter dlatego, że wtedy gracz dotyka podłoża.


Jak zrobisz doubleJump globalnie/statycznie, to po prostu wszystkie odniesienia do niego pozmieniasz.

0

@Spine: Zrobiłem to tak ale nie do końca wszystko działa ponieważ dostałem informacje o wielu błędach pewnie jest to moja wina ale nie wiem co tu poprawić, wiem moje zdolności programistyczne nie są wzorowe.

public class ogcontrol : MonoBehaviour
{
    public float chodz;
    public float bieganie;
    private float aktual;
    public float mouseSens;
    public float jumpPlayer;
    private Rigidbody rb;
    private int jumpLeft = 2;
    public float ilosc;

    bool doubleJump = false;
   
    public DoubleJumpActivate()
    {
        doubleJump = true;
    }
}
  private void OnCollisionEnter(Collision collision)
    {
        if (doubleJump)
        {
            jumpLeft = 2;
        }
        else
        {
            jumpLeft = 1;
        }
    }

public class punkt : MonoBehaviour
{

    void OnTriggerEnter(Collider collison)
    {
        ogcontrol.instance.DoubleJumpActivate();
        Destroy(gameObject);
    }

}
0

A zrobiłeś to co Ci wcześniej napisałem?

Spine napisał(a):

Żeby zrobić Singleton, dodaj w ciele klasy ogcontrol:

public static ogcontrol instance;

W metodzie Start albo Awake dopisz:

instance = this;

Gotowe ;)

0

@Spine: Tak zrobiłem to

    public static ogcontrol instance;
   void Start()
    {

        aktual = chodz;
        motor = GetComponent<jddsped>();
        rb = GetComponent<Rigidbody>();
        instance = this;
        
    }

błędy jakie mi się do tego wyświetlają to:
'ogcontrol' does not contain a definition for 'DoubleJumpActivate' and no accessible extension method 'DoubleJumpActivate' accepting a first argument of type 'ogcontrol' could be found (are you missing a using directive or an assembly reference?) i chodzi tu o skrypt "punkt"

Method must have a return type i chodzi tu o tą linijkie:

 public DoubleJumpActivate()
    {
        doubleJump = true;
    }
1

No tak... mój błąd, ma być

public void DoubleJumpActivate()

zamiast

public DoubleJumpActivate()

Wybacz...

1

@Spine: Faktycznie to było problemem, Dziękuje ci bardzo za pomoc już wszystko działa jak należy :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1