|
今天,为大家分享一下,如何做到一个虚拟摇杆实现物体的移动和特定的操作。下面是简单通过虚拟摇杆可以实现摩托车的行驶。【PS:因为项目代码比较多,也许文章讲得不够全面清楚,希望大家能多多包涵。
另外受帖子字数限制,代码只能发部分,可以加群:575561285 讨论】
好吧!废话不多讲,直接进入主题吧!
1.新建unity3d 项目,然后自己可以合理搭一个场景,导入需要的资源,例如,我这边会导入一些摩托车的模型。
2.首先考虑的是摩托车自身属性设置,然后可以给他们挂上脚本,属性:Pro_bike 5.js,控制声音:Bike_sound.js ,刹车控制:Skid Marks.js;
然后具体的代码如下:
Pro_bike 5.js
Bike_sound.js
- #pragma strict
- /// Writen by Boris Chuprin smokerr@mail.ru
- var linkToBike : pro_bike5;// making a link to corresponding bike's script
- //why it's here ? because you might use this script with many bikes in one scene
- var lastGear : int;//we need to know what gear is now
- private var highRPMAudio : AudioSource;// makeing second audioSource for mixing idle and high RPMs
- private var skidSound : AudioSource;// makeing another audioSource for skidding sound
- // creating sounds(Link it to real sound files at editor)
- var engineStartSound : AudioClip;
- var gearingSound : AudioClip;
- var IdleRPM : AudioClip;
- var highRPM : AudioClip;
- var skid : AudioClip;
- //we need to know is any wheel skidding
- var isSkidingFront : boolean = false;
- var isSkidingRear : boolean = false;
- private var ctrlHub : GameObject;// gameobject with script control variables
- private var outsideControls : controlHub;// making a link to corresponding bike's scriptt
- function Start () {
- ctrlHub = GameObject.Find("gameScenario");//link to GameObject with script "controlHub"
- outsideControls = ctrlHub.GetComponent(controlHub);//to connect c# mobile control script to this one
-
- //assign sound to audioSource
- highRPMAudio = gameObject.AddComponent(AudioSource);
- highRPMAudio.loop = true;
- highRPMAudio.playOnAwake = false;
- highRPMAudio.clip = highRPM;
- highRPMAudio.pitch = 0;
- highRPMAudio.volume = 0.0;
- //same assign for skid sound
- skidSound = gameObject.AddComponent(AudioSource);
- skidSound.loop = false;
- skidSound.playOnAwake = false;
- skidSound.clip = skid;
- skidSound.pitch = 1.0;
- skidSound.volume = 1.0;
-
- //real-time linking to current bike
- linkToBike = this.GetComponent(pro_bike5);
- GetComponent.<AudioSource>().PlayOneShot(engineStartSound);
- playEngineWorkSound();
- lastGear = linkToBike.CurrentGear;
- }
- function Update(){
-
- //Idle plays high at slow speed and highRPM sound play silent at same time. And vice versa.
- GetComponent.<AudioSource>().pitch = Mathf.Abs(linkToBike.EngineRPM / linkToBike.MaxEngineRPM) + 1.0;
- GetComponent.<AudioSource>().volume = 1.0 - (Mathf.Abs(linkToBike.EngineRPM / linkToBike.MaxEngineRPM));
- highRPMAudio.pitch = Mathf.Abs(linkToBike.EngineRPM / linkToBike.MaxEngineRPM);
- highRPMAudio.volume = Mathf.Abs(linkToBike.EngineRPM / linkToBike.MaxEngineRPM);
- // all engine sounds stop when restart
- if (outsideControls.restartBike){
- GetComponent.<AudioSource>().Stop();
- GetComponent.<AudioSource>().pitch = 1.0;
- GetComponent.<AudioSource>().PlayOneShot(engineStartSound);
- playEngineWorkSound();
- }
-
- //gear change sound
- if (linkToBike.CurrentGear != lastGear){
- GetComponent.<AudioSource>().PlayOneShot(gearingSound);//звук переключения передач
- lastGear = linkToBike.CurrentGear;
- }
- //skids sound
- if (linkToBike.coll_rearWheel.sidewaysFriction.stiffness < 0.5 && !isSkidingRear && linkToBike.bikeSpeed >1){//почему 0.5 ? как бы лучше это обыграть ?
- skidSound.Play();
- isSkidingRear = true;
- } else if (linkToBike.coll_rearWheel.sidewaysFriction.stiffness >= 0.5 && isSkidingRear || linkToBike.bikeSpeed <=1){
- skidSound.Stop();
- isSkidingRear = false;
- }
- if (linkToBike.coll_frontWheel.brakeTorque >= (linkToBike.frontBrakePower-10) && !isSkidingFront && linkToBike.bikeSpeed >1){
- skidSound.Play();
- isSkidingFront = true;
- } else if (linkToBike.coll_frontWheel.brakeTorque < linkToBike.frontBrakePower && isSkidingFront || linkToBike.bikeSpeed <=1){
- skidSound.Stop();
- isSkidingFront = false;
- }
- }
- function playEngineWorkSound(){
- yield WaitForSeconds(1);//need a pause to hear ingnition sound first
- GetComponent.<AudioSource>().clip = IdleRPM;
- GetComponent.<AudioSource>().Play();
- highRPMAudio.Play();
- }
复制代码
Skid Marks.js
- #pragma strict
- var linkToBike : pro_bike5;
- var skidMarkDecal : Transform;
- private var hit : WheelHit;
- private var skidMarkPos : Vector3;
- private var rotationToLastSkidmark : Quaternion;
- private var lastSkidMarkPos : Vector3;
- private var relativePos : Vector3;
- function Start () {
- linkToBike = this.GetComponent(pro_bike5);
- }
- function FixedUpdate(){
- //skidmarks for rear wheel(braking drifting)
- if (linkToBike.coll_rearWheel.sidewaysFriction.stiffness < 0.5 && linkToBike.bikeSpeed >1){
- if (linkToBike.coll_rearWheel.GetGroundHit(hit)){
- skidMarkPos = hit.point;
- skidMarkPos.y += 0.02;
- skidMarkDecal.transform.localScale.x = 1.0;
- if (lastSkidMarkPos != Vector3.zero){
- relativePos = lastSkidMarkPos - skidMarkPos;
- rotationToLastSkidmark = Quaternion.LookRotation(relativePos);
- Instantiate(skidMarkDecal, skidMarkPos, rotationToLastSkidmark);
- }
- lastSkidMarkPos = skidMarkPos;
- }
- }
- //skidmarks for front wheel(braking)
- if (linkToBike.coll_frontWheel.brakeTorque >= (linkToBike.frontBrakePower-10) && linkToBike.bikeSpeed >1){
- if (linkToBike.coll_frontWheel.GetGroundHit(hit)){
- skidMarkPos = hit.point;
- skidMarkPos.y += 0.02;
- skidMarkDecal.transform.localScale.x = 0.6;
- if (lastSkidMarkPos != Vector3.zero){
- relativePos = lastSkidMarkPos - skidMarkPos;
- rotationToLastSkidmark = Quaternion.LookRotation(relativePos);
- Instantiate(skidMarkDecal, skidMarkPos, rotationToLastSkidmark);
- }
- lastSkidMarkPos = skidMarkPos;
- }
- }
- }
- function Update () {
- }
复制代码
【脚本参数设置如图】
3.接下来,我们需要在场景中,新建一个gameScenario游戏对象GameObject,作为整个游戏控制中心,并且在gameScenario对象中附加 速度控制:Speedometer.js
控制整个游戏对象:controlHub.cs
Speedometer.js
- //speedometer
- var GUIDashboard : Texture2D;
- var dashboardArrow : Texture2D;
- private var topSpeed: float;//220 for sport/ 180 for chopper
- private var stopAngle: float;//-200 for sport/ ... for chopper
- private var topSpeedAngle: float;
- var speed: float;
- //tachometer
- var chronoTex: Texture2D;
- private var topRPM: float;// 14000 for sport/ ... for chopper
- private var stopRPMAngle: float;//-200 for sport/... ... for chopper
- private var topRPMAngle: float;
- var RPM: float;
- //link to bike script
- var linkToBike : pro_bike5;
- function Start () {
- linkToBike = GameObject.Find("rigid_bike").GetComponent("pro_bike5");
- findCurrentBike();
- }
- function OnGUI() {
- // speedometer
- GUI.DrawTexture(Rect(Screen.width*0.85, Screen.height*0.55, GUIDashboard.width/2, GUIDashboard.height/2), GUIDashboard);
- var centre = Vector2(Screen.width*0.85 + GUIDashboard.width / 4, Screen.height*0.55 + GUIDashboard.height / 4);
- var savedMatrix = GUI.matrix;
- var speedFraction = speed / topSpeed;
- var needleAngle = Mathf.Lerp(stopAngle, topSpeedAngle, speedFraction);
- GUIUtility.RotateAroundPivot(needleAngle, centre);
- GUI.DrawTexture(Rect(centre.x, centre.y - dashboardArrow.height/4, dashboardArrow.width/2, dashboardArrow.height/2), dashboardArrow);
- GUI.matrix = savedMatrix;
-
- //tachometer
- GUI.DrawTexture(Rect(Screen.width*0.65, Screen.height*0.5, chronoTex.width/1.5, chronoTex.height/1.5), chronoTex);
- var centreTacho = Vector2(Screen.width*0.65 + chronoTex.width / 3, Screen.height*0.5+ chronoTex.height / 3);
- var savedTachoMatrix = GUI.matrix;
- var tachoFraction = RPM / topRPM;
- var needleTachoAngle = Mathf.Lerp(stopRPMAngle, topRPMAngle, tachoFraction);
- GUIUtility.RotateAroundPivot(needleTachoAngle, centreTacho);
- GUI.DrawTexture(Rect(centreTacho.x, centreTacho.y - dashboardArrow.height/3, dashboardArrow.width/1.5, dashboardArrow.height/1.5), dashboardArrow);
- GUI.matrix = savedTachoMatrix;
- }
- function FixedUpdate(){
- speed = linkToBike.bikeSpeed;
- RPM = linkToBike.EngineRPM;
- }
- function findCurrentBike(){
- var curBikeName : GameObject;
- curBikeName = GameObject.Find("rigid_bike");
- if (curBikeName != null){
- SetSpeedometerSettings("sport");
- return;
- }
-
- }
- function SetSpeedometerSettings(par : String){
- if (par == "sport"){
- topSpeed = 210;
- stopAngle = -215;
- topSpeedAngle = 0;
- topRPM = 12000;
- stopRPMAngle = -200;
- topRPMAngle = 0;
- yield WaitForSeconds(0.5);
- var linkToBike1 = GameObject.Find("rigid_bike").GetComponent("pro_bike5");
- linkToBike = linkToBike1;
- }
- }
复制代码 controlHub.cs
- using UnityEngine;
- using System.Collections;
- //this is script contains all variables translated to bike's script.
- //so, it's just a holder for all control variables
- //mobile/keyboard scripts sends nums(float, int, bools) to this one
- public class controlHub : MonoBehaviour {//need that for mobile controls
-
- public float Vertical;//variable translated to bike script for bike accelerate/stop and leaning
- public float Horizontal;//variable translated to bike script for pilot's mass shift
-
- public float VerticalMassShift;//variable for pilot's mass translate along bike
- public float HorizontalMassShift;//variable for pilot's mass translate across bike
- public bool ESPMode;//variable for turn ESP on and off
- public bool rearBrakeOn;//this variable says to bike's script to use rear brake
- public bool restartBike;//this variable says to bike's script restart
- public bool fullRestartBike; //this variable says to bike's script to full restart
- public bool reverse;//for reverse speed
- }
复制代码
4.场景中相机的跟随和切换类:camSwitcher.cs;
- using UnityEngine;
- using System.Collections;
- public class camSwitcher : MonoBehaviour
- {
- public Camera backCamera;
- public Camera aroundCamera;
- public Transform cameraTarget;
- private Camera currentCamera;
- //////////////////// for back Camera
- float dist = 3.0f;
- float height = 1.0f;
- //////////////////// for around Camera
- private float distance = 3.0f;
- private float xSpeed = 10.0f;
- private float ySpeed = 10.0f;
-
- private float yMinLimit = -90;
- private float yMaxLimit = 90;
-
- private float distanceMin = 2;
- private float distanceMax = 10;
-
- private float x = 0.0f;
- private float y = 0.0f;
-
- private float smoothTime = 0.2f;
-
- private float xSmooth = 0.0f;
- private float ySmooth = 0.0f;
- private float xVelocity = 0.0f;
- private float yVelocity = 0.0f;
- //new camera behaviour
- private float currentTargetAngle;
-
- private GameObject ctrlHub;// gameobject with script control variables
- private controlHub outsideControls;// making a link to corresponding bike's script
-
- // Use this for initialization
- void Start ()
- {
- ctrlHub = GameObject.Find("gameScenario");//link to GameObject with script "controlHub"
- outsideControls = ctrlHub.GetComponent<controlHub>();//to connect c# mobile control script to this one
- backCamera.enabled = true;
- aroundCamera.enabled = false;
- currentCamera = backCamera;
-
- if (GetComponent<Rigidbody> ()) GetComponent<Rigidbody> ().freezeRotation = true;
-
- currentTargetAngle = cameraTarget.transform.eulerAngles.z;
- }
-
- // Update is called once per frame
- void LateUpdate ()
- {
- #if UNITY_STANDALONE || UNITY_WEBPLAYER// turn camera rotaion ONLY for mobile for free touch screen anywhere
- if (Input.GetMouseButton (1)) {
- backCamera.enabled = false;
- aroundCamera.enabled = true;
- backCamera.gameObject.SetActive (false);
- aroundCamera.gameObject.SetActive (true);
- currentCamera = aroundCamera;
-
-
- x += Input.GetAxis ("Mouse X") * xSpeed;
- y -= Input.GetAxis ("Mouse Y") * ySpeed;
-
- y = Mathf.Clamp (y, yMinLimit, yMaxLimit);
-
-
-
- xSmooth = Mathf.SmoothDamp (xSmooth, x, ref xVelocity, smoothTime);
- ySmooth = Mathf.SmoothDamp (ySmooth, y, ref yVelocity, smoothTime);
-
-
- distance = Mathf.Clamp (distance + Input.GetAxis ("Mouse ScrollWheel") * distance, distanceMin, distanceMax);
-
-
- currentCamera.transform.localRotation = Quaternion.Euler (ySmooth, xSmooth, 0);
- currentCamera.transform.position = currentCamera.transform.rotation * new Vector3 (0.0f, 0.0f, -distance) + cameraTarget.position;
- } else {
- #endif
- backCamera.enabled = true;
- aroundCamera.enabled = false;
- backCamera.gameObject.SetActive (true);
- aroundCamera.gameObject.SetActive (false);
- currentCamera = backCamera;
-
- //////////////////// code for back Camera
- backCamera.fieldOfView = backCamera.fieldOfView + outsideControls.Vertical * 20f * Time.deltaTime;
- if (backCamera.fieldOfView > 85) {
- backCamera.fieldOfView = 85;
- }
- if (backCamera.fieldOfView < 50) {
- backCamera.fieldOfView = 50;
- }
- if (backCamera.fieldOfView < 60) {
- backCamera.fieldOfView = backCamera.fieldOfView += 10f * Time.deltaTime;
- }
- if (backCamera.fieldOfView > 60) {
- backCamera.fieldOfView = backCamera.fieldOfView -= 10f * Time.deltaTime;
- }
-
- float wantedRotationAngle = cameraTarget.eulerAngles.y;
- float wantedHeight = cameraTarget.position.y + height;
- float currentRotationAngle = currentCamera.transform.eulerAngles.y;
- float currentHeight = currentCamera.transform.position.y;
-
- currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, 3 * Time.deltaTime);
- currentHeight = Mathf.Lerp (currentHeight, wantedHeight, 2 * Time.deltaTime);
-
- Quaternion currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
- currentCamera.transform.position = cameraTarget.position;
- currentCamera.transform.position -= currentRotation * Vector3.forward * dist;
- currentCamera.transform.position = new Vector3 (currentCamera.transform.position.x, currentHeight, currentCamera.transform.position.z);
- currentCamera.transform.LookAt (cameraTarget);
- //New camera features.
- //Now camera leaning with biker, so horizon is not always horizontal :)
- //If you don't like it, just disable
- //from this -----------------------------------------------------------------------
- // rotate camera according with bike leaning
- if (cameraTarget.transform.eulerAngles.z >0 && cameraTarget.transform.eulerAngles.z < 180) {
- currentTargetAngle = cameraTarget.transform.eulerAngles.z/10;
- }
- if (cameraTarget.transform.eulerAngles.z >180){
- currentTargetAngle = -(360-cameraTarget.transform.eulerAngles.z)/10;
- }
- currentCamera.transform.rotation = Quaternion.Euler (height*10, currentRotationAngle, currentTargetAngle);
- //to this -------------------------------------------------------------------------
- #if UNITY_STANDALONE || UNITY_WEBPLAYER// turn camera rotaion ONLY for mobile for free touch screen anywhere
- }
- #endif
- }
- }
复制代码
5.讲到这一步是比较关键的,正是通过GUI做出虚拟摇杆,虚拟摇杆控制类:mobileControls.cs;
6.最后直接运行看效果。【PS:HAHA!有空动手练练也是蛮有趣的】
|
|