常常看到手機遊戲都有Joystick 圖示來控制角色移動,按鈕控制角色: 跳躍,攻擊.....等等的功能,大概花時間研究了一下,可以用UnityUI的屬性方式來進行。
操作之前,我們可以理解成介面都是由圖片方式來進行與操作者互動。
例如:
- 角色攻擊,玩家就會去點擊攻擊的指令,那個指令就可以當成是一個按鈕方式來進行觸發。
- 按鈕圖示可以換成攻擊圖片與做出點擊按鈕震動動畫效果與玩家進行人機互動方式呈現。
以上圖示Joystick 圖示按鈕
結果:
以下藉由Unity.EventSystems interface 方式來進行撰寫功能。
Joystick -- C# 腳本
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Joystick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
// Init
protected Image container;
protected Image joystick;
protected Vector3 InputDirection = Vector3.zero;
public void OnDrag(PointerEventData ped)
{
Vector2 position = Vector2.zero;
// Get InputDirection
RectTransformUtility.ScreenPointToLocalPointInRectangle(
container.rectTransform,
ped.position,
ped.pressEventCamera,
out position
);
float x = (position.x / container.rectTransform.sizeDelta.x);
float y = (position.y / container.rectTransform.sizeDelta.y);
InputDirection = new Vector3(x, y, 0);
InputDirection = (InputDirection.magnitude > 1) ? InputDirection.normalized : InputDirection;
// Define the area in which joystick can move around
joystick.rectTransform.anchoredPosition = new Vector3(
InputDirection.x * container.rectTransform.sizeDelta.x / 3,
InputDirection.y * container.rectTransform.sizeDelta.y / 3
);
}
public void OnPointerDown(PointerEventData ped)
{
OnDrag(ped);
}
public void OnPointerUp(PointerEventData ped)
{
InputDirection = Vector3.zero;
joystick.rectTransform.anchoredPosition = Vector3.zero;
}
}
InterfaceOBJ -- C# 腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
public class InterfaceOBJ
{
private Image imageObj;
private Button buttonObj;
private interfaceObj interfaceObj;
public InterfaceOBJ(Image imag, interfaceObj interfaceObj)
{
this.imageObj = imag;
this.interfaceObj = interfaceObj;
}
public InterfaceOBJ(Button button, interfaceObj interfaceObj)
{
this.buttonObj = button;
this.interfaceObj = interfaceObj;
}
// image
public void image(float pointX, float pointY, float sizeX, float sizeY)
{
interfaceObj.image(imageObj, pointX, pointY, sizeX, sizeY);
}
// button
public void button(float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick)
{
interfaceObj.button(buttonObj, pointX, pointY, sizeX, sizeY, onClick);
}
}
public interface interfaceObj
{
void image(Image image, float pointX, float pointY, float sizeX, float sizeY);
void button(Button button, float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick);
}
InterfaceObj -- C# 腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class InterfaceObj : interfaceObj
{
public void button(Button button, float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick)
{
try
{
button.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
button.image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, sizeY);
button.onClick.AddListener(onClick);
}
catch { }
}
public void image(Image image, float pointX, float pointY, float sizeX, float sizeY)
{
try
{
image.rectTransform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);
}
catch { }
}
}
Layout_Main -- C# 腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Layout_Main : Joystick
{
public Image fixedJoystick_image, handle_image;
public Button jump_btn;
InterfaceOBJ fixedJoystick, jump;
public static Vector3 DIRCTION;
public static bool JUMP_SW;
// 計時器
private float timeCount;
private float timeCD = 1f;
public static bool JUMP_ACTIVE;
private void Start()
{
base.container = fixedJoystick_image;
base.joystick = handle_image;
fixedJoystick = new InterfaceOBJ(fixedJoystick_image, new InterfaceObj());
fixedJoystick.image(0.23f, 0.4f, 0.2f, 0.35f);
jump = new InterfaceOBJ(jump_btn, new InterfaceObj());
jump.button(1.68f, 0.42f, 0.2f, 80, jump_onClkck);
}
private void Update()
{
DIRCTION = base.InputDirection;
JUMP_ACTIVE = jumpCd();
}
void jump_onClkck()
{
if (JUMP_ACTIVE == true)
{
JUMP_SW = true;
timeCount = timeCD;
}
}
// 跳躍冷卻時間
public bool jumpCd()
{
return ((timeCount -= Time.deltaTime) <= 0) ? true : false;
}
}
Player -- C# 腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
Rigidbody rigidbody;
private float gravity = 10.0f, maxVelocityChange = 50f, jumpHeight = 1f;
public float speed;
void Start()
{
rigidbody = GetComponent();
rigidbody.freezeRotation = true;
rigidbody.useGravity = false;
}
private void FixedUpdate()
{
if(Layout_Main.DIRCTION.magnitude != 1)
{
Vector3 position = new Vector3(Layout_Main.DIRCTION.x * speed, 0,
Layout_Main.DIRCTION.y * speed);
position = transform.TransformDirection(position);
Vector3 velocity = rigidbody.velocity;
Vector3 velocityChange = (position - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0;
rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
if (Layout_Main.JUMP_SW)
rigidbody.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
if (Layout_Main.JUMP_ACTIVE == false)
Layout_Main.JUMP_SW = false;
}
rigidbody.AddForce(new Vector3(0, -gravity * rigidbody.mass, 0));
}
// Jump
float CalculateJumpVerticalSpeed()
{
return Mathf.Sqrt(2 * jumpHeight * gravity);
}
}
Unity 介面設計:
- Canvas - Unity UI(一定要)
- FixedJoystick - Unity UI (Image)
- Handle - Unity UI (Image) - 當FixedJoystick子物件
- Handle 設定Width: 50, Height: 50
- Handle - Unity UI (Image) - 當FixedJoystick子物件
- Jump_Btn - Unity UI (Image)
- EventSystem - Unity UI (一定要)
- Player - 3D物件(本文使用Unity內建物件)
- Plane - 3D物件(本文使用內建物件)
Canvas 物件:
- 插入Layout_Main腳本
Player 物件:
- 插入Player腳本
沒有留言:
張貼留言