0
\$\begingroup\$

There are some scripts they are all connected :

The first script define the press key, I added keycode B and named it as BackToBase :

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

public class ControlPanel : MonoBehaviour {
    public AudioSource MusicSound;

    [SerializeField]
    KeyCode SpeedUp = KeyCode.Space;
    [SerializeField]
    KeyCode SpeedDown = KeyCode.C;
    [SerializeField]
    KeyCode Forward = KeyCode.W;
    [SerializeField]
    KeyCode Back = KeyCode.S;
    [SerializeField]
    KeyCode Left = KeyCode.A;
    [SerializeField]
    KeyCode Right = KeyCode.D;
    [SerializeField]
    KeyCode TurnLeft = KeyCode.Q;
    [SerializeField]
    KeyCode TurnRight = KeyCode.E;
    [SerializeField]
    KeyCode MusicOffOn = KeyCode.M;
    [SerializeField]
    KeyCode BackToBase = KeyCode.B;

    private KeyCode[] keyCodes;

    public Action<PressedKeyCode[]> KeyPressed;
    private void Awake()
    {
        keyCodes = new[] {
                            SpeedUp,
                            SpeedDown,
                            Forward,
                            Back,
                            Left,
                            Right,
                            TurnLeft,
                            TurnRight,
                            BackToBase
                        };

    }

    void Start () {
    
    }

    void FixedUpdate ()
    {
        var pressedKeyCode = new List<PressedKeyCode>();
        for (int index = 0; index < keyCodes.Length; index++)
        {
            var keyCode = keyCodes[index];
            if (Input.GetKey(keyCode))
                pressedKeyCode.Add((PressedKeyCode)index);
        }

        if (KeyPressed != null)
            KeyPressed(pressedKeyCode.ToArray());

        // for test
        if (Input.GetKey(MusicOffOn))
        {
           if (  MusicSound.volume == 1) return;
/*            if (MusicSound.isPlaying)
                MusicSound.Stop();
            else*/
                MusicSound.volume = 1;
                MusicSound.Play();
        }
      
    }
}

Then helper class :

public enum PressedKeyCode
{
    SpeedUpPressed,
    SpeedDownPressed,
    ForwardPressed,
    BackPressed,
    LeftPressed,
    RightPressed,
    TurnLeftPressed,
    TurnRightPressed,
    BackToBase
}

And last the helicopter controller :

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class HelicopterController : MonoBehaviour
{
    public AudioSource HelicopterSound;
    public ControlPanel ControlPanel;
    public Rigidbody HelicopterModel;
    public HeliRotorController MainRotorController;
    public HeliRotorController SubRotorController;

    public float TurnForce = 3f;
    public float ForwardForce = 10f;
    public float ForwardTiltForce = 20f;
    public float TurnTiltForce = 30f;
    public float EffectiveHeight = 100f;

    public float turnTiltForcePercent = 1.5f;
    public float turnForcePercent = 1.3f;

    private float _engineForce;

    private Vector3 originalPlanePosition;
    private Quaternion originalPlaneRotation;
    public GameObject helicopterPlatform;
    public float lookAtSpeed;
    public float thresholdDegrees;
    private bool hasRotate = false;

    public float EngineForce
    {
        get { return _engineForce; }
        set
        {
            MainRotorController.RotarSpeed = value * 80;
            SubRotorController.RotarSpeed = value * 40;
            HelicopterSound.pitch = Mathf.Clamp(value / 40, 0, 1.2f);
            if (UIGameController.runtime.EngineForceView != null)
                UIGameController.runtime.EngineForceView.text = string.Format("Engine value [ {0} ] ", (int)value);

            _engineForce = value;
        }
    }

    private Vector2 hMove = Vector2.zero;
    private Vector2 hTilt = Vector2.zero;
    private float hTurn = 0f;
    public bool IsOnGround = true;

    // Use this for initialization
    void Start ()
    {
        originalPlanePosition = transform.position;
        originalPlaneRotation = transform.rotation;

        ControlPanel.KeyPressed += OnKeyPressed;
    }

    void Update () {
    }
  
    void FixedUpdate()
    {
        LiftProcess();
        MoveProcess();
        TiltProcess();

        if (hasRotate == true)
        {
            Vector3 targetDirection = helicopterPlatform.transform.position - transform.position;
            Vector3 newDirection = Vector3.RotateTowards(transform.forward, targetDirection, lookAtSpeed * Time.deltaTime, 0.0f);
            transform.rotation = Quaternion.LookRotation(newDirection);

            if (Vector3.Angle(newDirection, targetDirection) < thresholdDegrees)
            {
                hasRotate = false;
            }
        }
    }

    private void MoveProcess()
    {
            var turn = TurnForce * Mathf.Lerp(hMove.x, hMove.x * (turnTiltForcePercent - Mathf.Abs(hMove.y)), Mathf.Max(0f, hMove.y));
            hTurn = Mathf.Lerp(hTurn, turn, Time.fixedDeltaTime * TurnForce);
            HelicopterModel.AddRelativeTorque(0f, hTurn * HelicopterModel.mass, 0f);
            HelicopterModel.AddRelativeForce(Vector3.forward * Mathf.Max(0f, hMove.y * ForwardForce * HelicopterModel.mass));
    }

    private void LiftProcess()
    {
        var upForce = 1 - Mathf.Clamp(HelicopterModel.transform.position.y / EffectiveHeight, 0, 1);
        upForce = Mathf.Lerp(0f, EngineForce, upForce) * HelicopterModel.mass;
        HelicopterModel.AddRelativeForce(Vector3.up * upForce);
    }

    private void TiltProcess()
    {
        hTilt.x = Mathf.Lerp(hTilt.x, hMove.x * TurnTiltForce, Time.deltaTime);
        hTilt.y = Mathf.Lerp(hTilt.y, hMove.y * ForwardTiltForce, Time.deltaTime);
        HelicopterModel.transform.localRotation = Quaternion.Euler(hTilt.y, HelicopterModel.transform.localEulerAngles.y, -hTilt.x);
    }

    private void OnKeyPressed(PressedKeyCode[] obj)
    {
        float tempY = 0;
        float tempX = 0;

        // stable forward
        if (hMove.y > 0)
            tempY = - Time.fixedDeltaTime;
        else
            if (hMove.y < 0)
                tempY = Time.fixedDeltaTime;

        // stable lurn
        if (hMove.x > 0)
            tempX = -Time.fixedDeltaTime;
        else
            if (hMove.x < 0)
                tempX = Time.fixedDeltaTime;


        foreach (var pressedKeyCode in obj)
        {
            switch (pressedKeyCode)
            {
                case PressedKeyCode.SpeedUpPressed:

                    EngineForce += 0.1f;
                    break;
                case PressedKeyCode.SpeedDownPressed:

                    EngineForce -= 0.12f;
                    if (EngineForce < 0) EngineForce = 0;
                    break;

                case PressedKeyCode.ForwardPressed:

                    if (IsOnGround) break;
                    tempY = Time.fixedDeltaTime;
                    break;
                case PressedKeyCode.BackPressed:

                    if (IsOnGround) break;
                    tempY = -Time.fixedDeltaTime;
                    break;
                case PressedKeyCode.LeftPressed:

                    if (IsOnGround) break;
                    tempX = -Time.fixedDeltaTime;
                    break;
                case PressedKeyCode.RightPressed:

                    if (IsOnGround) break;
                    tempX = Time.fixedDeltaTime;
                    break;
                case PressedKeyCode.TurnRightPressed:
                    {
                        if (IsOnGround) break;
                        var force = (turnForcePercent - Mathf.Abs(hMove.y)) * HelicopterModel.mass;
                        HelicopterModel.AddRelativeTorque(0f, force, 0);
                    }
                    break;
                case PressedKeyCode.TurnLeftPressed:
                    {
                        if (IsOnGround) break;

                        var force = -(turnForcePercent - Mathf.Abs(hMove.y)) * HelicopterModel.mass;
                        HelicopterModel.AddRelativeTorque(0f, force, 0);
                    }
                    break;
                case PressedKeyCode.BackToBase:
                    {

                        hasRotate = true;
                    }
                    break;
            }
        }

        hMove.x += tempX;
        hMove.x = Mathf.Clamp(hMove.x, -1, 1);

        hMove.y += tempY;
        hMove.y = Mathf.Clamp(hMove.y, -1, 1);

    }

    private void OnCollisionEnter()
    {
        IsOnGround = true;
    }

    private void OnCollisionExit()
    {
        IsOnGround = false;
    }
}

In the last script I added a new flag name hasRotate and I set it to true in this place when pressing the B key :

case PressedKeyCode.BackToBase:
                        {
    
                            hasRotate = true;
                        }
                        break;

Then in the FixedUpdate I added this part :

if (hasRotate == true)
            {
                Vector3 targetDirection = helicopterPlatform.transform.position - transform.position;
                Vector3 newDirection = Vector3.RotateTowards(transform.forward, targetDirection, lookAtSpeed * Time.deltaTime, 0.0f);
                transform.rotation = Quaternion.LookRotation(newDirection);
    
                if (Vector3.Angle(newDirection, targetDirection) < thresholdDegrees)
                {
                    hasRotate = false;
                }
            }

When I press the B key the helicopter rotate smooth facing his platform base I named it here as helicopterPlatform.

This is a screenshot when starting the game the helicopter is on ground on the platform base :

Helicopter on platform at start

This is the platform settings :

Platform

When I press down on the SHIFT key it gives the helicopter power and then the helicopter lift up then pressing W moving the helicopter forward and then when leaving the W the helicopter idle in place.

This is when the helicopter idle in place after moved it a bit from the platform base :

Idle

Then I press once on the B key the helicopter rotating turn smooth facing the platform base and keep idle:

Helicopter facing the platform base

At this point I want to have two options :

  • When pressing on the B key once the helicopter automatic will rotate facing the platform base and automatic will move to it then when the helicopter is above the platform it will rotate if needed to be the same rotation when the hleicopter lifted first time and then the helicopter will move down landing until hitting the ground.

  • Second option, When I press once the B key the helicopter will rotate facing the platform base but then will not move to it and land automatic but will give me free flying mode like when running the game and I will decide when to flight to.

Now the only thing I did is that the helciopter is rotating smooth facing the platform base.

The problem I'm facing now :

  • After pressing once on the B key and the helicopter is facing the platform when I press on D or A to rotate the helicopter right or left I press on D for example the helicopter rotate a bit to the right when I leave the D key the helicopter automatic rotating facing the platform again not sure why.

The scripts are a bit long but they are all connected to each other.

\$\endgroup\$
  • \$\begingroup\$ Are you sure if (Vector3.Angle(newDirection, targetDirection) < thresholdDegrees) { hasRotate = false; } is hit? Try putting breakpoint there and check. \$\endgroup\$ – eLTomis Jul 31 at 10:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.