本教程开始分享教学内容:Unity游戏基础,部分内容会包括Blender建模基础,Shader基础,动画基础等等,教程面向:建模、技术美术、游戏前端、游戏后端基础,适合美术与设计(数媒、环设、动画、产设、视传、绘画)专业、计算机(计算机科学与技术、软件工程、数媒)的同学学习。
本章节为第二章节,面向比较深层次的技术,包括shader基础、跨平台兼容(桌面端、移动端)
一、打开Adobe Illustrator
设计3个图案(摇杆可以使用其他图片替代,后期会专门为摇杆制作效果)
这些图标只在移动端出现,所以我们需要新建一个脚本来处理移动端和桌面端的图标,导出注意要透明
二、打开Unity
按照之前的教程做,我们截图跨平台部分只针对MobileControls操作,然后其他脚本的代码需要修改,修改部分需要认真核对,如果我核对出现错误,请积极指出错误!
1、要善于管理层级关系(直接使用空物体来作为父对象,相当于文件管理的文件夹的作用)
2、导入我们的图片作为控件
建议都放在Texture文件夹里面,注意了,此时的图片文件还不能正常使用,我们点击一个图片文件,在inspector窗口里面把 Texture Type改成Sprite(2D and UI),这样后期我们可以改白色部分的颜色
3、部署控件
(需要4个Image控件,层级关系如上图的MobileControls)
2D场景,去除了setting Form的设计方位,红色摇杆一定要在中间
三、注册事件、新建脚本
通过对控件的Add Components来添加EventTrigger ,疾跑同理
在Script文件夹里面新建一个脚本:PlatformInputManager,并且挂载给backController(黄色底的摇杆底座)
// PlatformInputManager.cs (修改版)
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class PlatformInputManager : MonoBehaviour
{
public static PlatformInputManager Instance { get; private set; }
[Header("移动控制")]
public MoveControl mobileMoveControl;
public GameObject mobileControls;
[Header("平台设置")]
public bool forceMobile = false;
private bool isMobilePlatform = false;
private bool isInitialized = false;
private bool isjumpdown;
private bool isSpeed;
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
return;
}
DetectPlatform();
SetupControls();
isInitialized = true;
}
void DetectPlatform()
{
isMobilePlatform = forceMobile ||
Application.isMobilePlatform ||
Application.platform == RuntimePlatform.Android ||
Application.platform == RuntimePlatform.IPhonePlayer;
}
void SetupControls()
{
if (mobileControls != null)
{
mobileControls.SetActive(isMobilePlatform);
}
if (!isMobilePlatform)
{
Cursor.lockState = CursorLockMode.Locked;
}
else
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
}
public bool IsMobile()
{
return isMobilePlatform;
}
public Vector2 GetMovementInput()
{
if (!isInitialized) return Vector2.zero;
if (isMobilePlatform && mobileMoveControl != null)
{
return mobileMoveControl.GetInputDirection();
}
else
{
return new Vector2(
Input.GetAxis("Horizontal"),
Input.GetAxis("Vertical")
);
}
}
public Vector2 GetLookInput()
{
if (!isInitialized) return Vector2.zero;
if (isMobilePlatform)
{
return GetMobileLookInput();
}
else
{
return new Vector2(
Input.GetAxis("Mouse X"),
Input.GetAxis("Mouse Y")
);
}
}
private Vector2 GetMobileLookInput()
{
// 简单的触摸输入处理
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
// 只处理在屏幕右半部分的触摸
if (touch.position.x > Screen.width / 2)
{
return touch.deltaPosition * 0.02f; // 灵敏度调整
}
}
return Vector2.zero;
}
public void JumpDown()
{
isjumpdown = true;
}
public void JumpUp()
{
isjumpdown = false;
}
public void SpeedDown()
{
isSpeed = true;
}
public void SpeedUp()
{
isSpeed = false;
}
public bool IsJumpPressed()
{
if (!isInitialized) return false;
if (isMobilePlatform)
{
return isjumpdown;
}
else
{
return Input.GetButtonDown("Jump");
}
}
public bool IsSprintPressed()
{
if (!isInitialized) return false;
if (isMobilePlatform)
{
return isSpeed;
}
else
{
return Input.GetKey(KeyCode.LeftShift);
}
}
// 添加一个方法来强制更新控制状态
public void RefreshControlState()
{
SetupControls();
}
}
设置参数
新建脚本,MoveControl:专门处理移动端摇杆事件,同样地,挂载给backController(黄底底座)
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class MoveControl : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
private RectTransform background;
private RectTransform handle;
private Vector2 inputDirection;
public static bool isDragging = false;
public float HandleRange = 1f;
public static bool isHandleIn;
void Start()
{
background = GetComponent<RectTransform>();
handle = transform.GetChild(0).GetComponent<RectTransform>();
inputDirection = Vector2.zero;
}
public void OnDrag(PointerEventData eventData)
{
isDragging = true;
Vector2 position = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
background,
eventData.position,
eventData.pressEventCamera,
out position))
{
position.x = (position.x / background.sizeDelta.x);
position.y = (position.y / background.sizeDelta.y);
inputDirection = new Vector2(position.x * 2, position.y * 2);
inputDirection = (inputDirection.magnitude > 1) ? inputDirection.normalized : inputDirection;
handle.anchoredPosition = new Vector2(
inputDirection.x * (background.sizeDelta.x / 2) * HandleRange,
inputDirection.y * (background.sizeDelta.y / 2) * HandleRange);
}
}
public void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
isDragging = false;
inputDirection = Vector2.zero;
handle.anchoredPosition = Vector2.zero;
}
public Vector2 GetInputDirection()
{
return inputDirection;
}
public float GetHorizontal()
{
return inputDirection.x;
}
public float GetVertical()
{
return inputDirection.y;
}
public bool IsDragging()
{
return isDragging;
}
}
参数设置
其中的private部分可以通过直接挂载摇杆实现,不需要获取子对象
四、修改其他代码
CameraController:Start方法
void Start()
{
// 确保 PlatformInputManager 已初始化
if (PlatformInputManager.Instance == null)
{
GameObject inputManager = new GameObject("PlatformInputManager");
inputManager.AddComponent<PlatformInputManager>();
}
// 移动端初始设置
if (PlatformInputManager.Instance.IsMobile())
{
Cursor.lockState = CursorLockMode.None;
isleave = false;
}
else
{
Cursor.lockState = CursorLockMode.Locked;
}
//以下代码不变
Vector3 angles = transform.eulerAngles;
currentX = angles.y;
currentY = angles.x;
targetDistance = distance;
cameraDirection = (transform.position - target.position).normalized;
}
HandleInput方法部分:
//需要大改
void HandleInput()//整合
{
// 根据平台获取不同的输入
if (PlatformInputManager.Instance.IsMobile())
{
HandleMobileInput();
}
else
{
HandleDesktopInput();
}
// 限制垂直角度
currentY = Mathf.Clamp(currentY, minVerticalAngle, maxVerticalAngle);
}
void HandleDesktopInput()//这一部分和上次的相同
{
// 桌面端输入处理
currentX += Input.GetAxis("Mouse X") * rotationSpeed;
currentY -= Input.GetAxis("Mouse Y") * rotationSpeed;
// 滚轮缩放
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll != 0)
{
distance -= scroll * zoomSpeed;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
}
}
void HandleMobileInput()//专门为移动端写的代码
{
// 检查是否正在使用摇杆
//Vector2 joystickInput = PlatformInputManager.Instance.GetMovementInput();
//isUsingJoystick = joystickInput.magnitude > 0.1f;
// 处理屏幕旋转(无论是否使用摇杆)
if (enableTouchRotation && Input.touchCount > 0)
{
// 遍历所有触摸点
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);
// 如果触摸点不在摇杆区域内,则处理为视角旋转
// 只处理在屏幕右半部分的触摸
if (touch.position.x > Screen.width / 2 && touch.phase == TouchPhase.Moved)
{
currentX += touch.deltaPosition.x * touchSensitivity * mobileRotationMultiplier;
currentY -= touch.deltaPosition.y * touchSensitivity * mobileRotationMultiplier;
// 限制垂直角度
currentY = Mathf.Clamp(currentY, minVerticalAngle, maxVerticalAngle);
}
}
}
// 处理双指缩放(无论是否使用摇杆)?
if (Input.touchCount == 2 & !MoveControl.isDragging)
{
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
float prevMagnitude = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float currentMagnitude = (touchZero.position - touchOne.position).magnitude;
float difference = currentMagnitude - prevMagnitude;
distance -= difference * zoomSpeed * 0.01f;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
}
}
PlayerMovement:几个跳跃、冲刺、需要修改的部分
void HandleJump()
{
if (PlatformInputManager.Instance.IsJumpPressed() && isGrounded)
{
playerVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
}
void HandleMovement()
{
// 通过PlatformInputManager获取输入
Vector2 input = PlatformInputManager.Instance.GetMovementInput();
float horizontal = input.x;
float vertical = input.y;
// 如果是移动端,调整移动速度
float speedMultiplier = PlatformInputManager.Instance.IsMobile() ?
mobileMoveSpeedMultiplier : 1f;
// 移动方向计算
Vector3 camForward = Vector3.Scale(cameraTransform.forward, new Vector3(1, 0, 1)).normalized;
Vector3 moveDirection = (camForward * vertical + cameraTransform.right * horizontal).normalized;
// 应用移动速度
Vector3 movement = moveDirection * moveSpeed * speedMultiplier * Time.deltaTime;
controller.Move(movement);
// 角色朝向移动方向
if (moveDirection.magnitude > 0.1f)
{
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
float rotationMultiplier = PlatformInputManager.Instance.IsMobile() ?
mobileRotationMultiplier : 1f;
transform.rotation = Quaternion.Slerp(
transform.rotation,
targetRotation,
rotateSpeed * rotationMultiplier * Time.deltaTime
);
}
if (isGrounded && playerVelocity.y < 0)
{
playerVelocity.y = -2;
}
playerVelocity.y += gravity * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
void CheckSpeed()
{
if (PlatformInputManager.Instance.IsSprintPressed())
{
moveSpeed = 15f;
}
else
{
moveSpeed = 5f;
}
}
五、部署在移动端上
本教程只部署安卓平台,其他跨平台相似,如果你没有安装安卓的SDK可以点击安装
点击Build 选一个文件夹命名为Bin-Android
连接手机数据线,导入,安装,完成!
Unity适用的平台:安卓机器版本不能太老,必须是安卓套壳或者原装安卓系统,鸿蒙系统目前不支持!老版本的安卓不支持,进去是玫红色无法操作。