2015年12月13日 星期日

Unity + logitech g27

使用 Logitech g27  跟Unity 製作搭配之前,所先要先下載 DirectX 安裝取得xinput1_3.dll ,這裡所使用x64位元,x86 目前沒進行測試。

如果使用 System.Windows.Forms.dll,請更改 .NET2.0  (PlayerSetting 位置)

DirectX  下載

Logitech G27 SDK 下載

Logitech G27 Driver 下載

System.Windows.Forms.dll 下載

Logitech G27  3個踏板 是分開數值,以往的Unity Input.GetAxis("Vertical") 有些不同

Logitech G27 圖片:




-------------------------------------------------

之前賽車程式來當範例:

標註: 紅色文字跟Logitech G27  SDK 相關

PlayerCar_Script (C#) :

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(AudioSource))]
public class PlayerCar_Script : MonoBehaviour {

    // These variables allow the script to power the wheels of the car.
    [SerializeField]
    WheelCollider frontLeftWheel, frontRightWheel, backLeftWheel, backRightWheel;

    /**
      * These variables are for the gears, the array is the list of ratios. The script
        uses the defined gear ratios to determine how much torque to apply to the wheels.
   */
    [SerializeField]
    float[] gearRatio;
    [SerializeField]
    float differentialRatio = 3.21f;
    [SerializeField]
    int currentGear = 0;

    /**
      * These variables are just for applying torque to the wheels and shifting gears.
        using the defined Max and Min Engine RPM, the script can determine what gear the
        car needs to be in.
     */
    [SerializeField]
    float engineTorque = 600f, maxEngineRPM = 700f, minEngineRPM = 1000f, engineRPM = 0f;
    [SerializeField]
    int frontWheelDrive = 1, rearWheelDrive = 1;

    // Center Of Mass
    [SerializeField]
    float comX = 0f, comY = 0f, comZ = 0f;

    private Rigidbody rigidbody;
    private AudioSource audioSource;

    // Use this for initialization
    void Start () {
        // I usually alter the center of mass to make the car more stable. I'ts less likely to flip this way.
        rigidbody = GetComponent<Rigidbody>();
        rigidbody.centerOfMass = new Vector3(comX, comY, comZ);

        audioSource = GetComponent<AudioSource>();
    }

    int vertical;

    // Update is called once per frame
    void Update () {

        if (LogitechGSDK.LogiUpdate() && LogitechGSDK.LogiIsConnected(0))
        {

            LogitechGSDK.DIJOYSTATE2ENGINES rec;
            rec = LogitechGSDK.LogiGetStateUnity(0);
            //update center of mass
            rigidbody.centerOfMass = new Vector3(comX, comY, comZ);

            /**
              * This is to limith the maximum speed of the car, adjusting the drag probably isn't the best way of doing it,
                but it's easy, and it doesn't interfere with the physics processing.
            */
            rigidbody.drag = rigidbody.velocity.magnitude / 250;

            // Compute the engine RPM based on the average RPM of the two wheels, then call the shift gear function
            engineRPM = Mathf.Abs(backLeftWheel.rpm + backRightWheel.rpm) / 2 * gearRatio[currentGear] * differentialRatio;
            if (engineRPM > 10000)
                engineRPM = 10000;
            if (engineRPM < 0)
                engineRPM = 0;
            shiftGears();

            /**
              * set the audio pitch to the percentage of RPM to the maximum RPM plus one, this makes the sound play
                up to twice it's pitch, where it will suddenly drop when it switches gears.
            */
            audioSource.pitch = Mathf.Abs(engineRPM / maxEngineRPM) + 0.5f;
            if (audioSource.pitch > 1.5f)
                audioSource.pitch = 1.5f;

            /**
              * finally, apply the values to the wheels.
                The torque applied is divided by the current gear, and
                multiplied by the user input variable.
            */

            vertical = (-Mathf.Abs(32767 - rec.lY)/2) + (Mathf.Abs(32767 - rec.lRz)/2);
           
            if (frontWheelDrive.Equals(1)) {

                frontLeftWheel.motorTorque = -engineTorque * gearRatio[currentGear] * differentialRatio * vertical;
                frontRightWheel.motorTorque = -engineTorque * gearRatio[currentGear] * differentialRatio * vertical;
            }

            if (rearWheelDrive.Equals(1))
            {
                backLeftWheel.motorTorque = -engineTorque * gearRatio[currentGear] * differentialRatio * vertical;
                backLeftWheel.motorTorque = -engineTorque * gearRatio[currentGear] * differentialRatio * vertical;
            }
           
            // the steer angle is an arbitrary value multiplied by the user input.
            frontLeftWheel.steerAngle = rec.lX / 1050;
            frontRightWheel.steerAngle = rec.lX / 1050;

        }else if (!LogitechGSDK.LogiIsConnected(0)) {
            System.Windows.Forms.MessageBox.Show("PLEASE PLUG IN A STEERING WHEEL OR A FORCE FEEDBACK CONTROLLER");
        }else {
            System.Windows.Forms.MessageBox.Show("THIS WINDOW NEEDS TO BE IN FOREGROUND IN ORDER FOR THE SDK TO WORK PROPERLY");
        }
    }
    void shiftGears(){

        /**
          * this funciton shifts the gears of the vehcile, it loops through all the gears, checking which will make
            the engine RPM fall within the desired range. The gear is then set to this "appropriate" value.
        */

        if (engineRPM >= maxEngineRPM)
        {
            int appropriateGear = currentGear;
            for (int i = 0; i < gearRatio.Length; i++)
            {
                if (Mathf.Abs(backLeftWheel.rpm + backRightWheel.rpm) / 2 * gearRatio[i] * differentialRatio < maxEngineRPM)
                {
                    appropriateGear = i;
                    break;
                }
            }
            currentGear = appropriateGear;
        }
    }
}



2015年12月1日 星期二

Unity editor basic apply (Unity 編輯視窗基本應用)

Unity Editor 應用注意:

Unity Edit need MonoBehaviour apply gameobjcet, so create script extends MonoBehaviour can use.
建立新的腳本,並且要繼承 MonoBehaviour,否則 Unity Editor  腳本不能套用在物件身上。

TestEdit (C#) : 

using UnityEngine;
using System.Collections;
using UnityEditor;

/**
  * Unity Edit need MonoBehaviour apply gameobjcet,
    so create script extends MonoBehaviour can use.
  */
[CustomEditor(typeof(PlayerTest))] 
public class TestEdit : Editor {

    Color color;

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
  
        // Color setting windows
        color = EditorGUILayout.ColorField("color",color);
        
        if (GUILayout.Button("color Setting")) {
            PlayerTest obj = target as PlayerTest; 
            obj.GetComponent<Renderer>().material.color = color;
        }   
    }
}

結果圖: