Thiết lập hiển thị
- Tạo một GameObject rỗng, đặt tên
KinectController, gắn các componentKinectManager,KinectGesturesvàOverlayController. - Trên
KinectManager, bậtComputeColorMapvàUseMultiSourceReader. - Cấu hình
Main Cameranhư camera foreground:Clear Flags:Depth onlyCulling Mask: bỏ chọnEverything, sau đó chọn tất cả các layer còn lạiClipping Planes:Near = 0.1,Far = 10Depth = 0
BackgroundCamera:Clear Flags:Solid ColorCulling Mask:EverythingDepth = -1
- Trong
OverlayController, đổi kiểu củaBackgroundImagethànhRawImagehoặcImage.Nếu dùng
RawImage:if (backgroundImage.texture == null) { backgroundImage.texture = manager.GetUsersClrTex(); }Nếu dùng
Image:Image image = backgroundImage.GetComponent<Image>(); if (image.material.mainTexture == null) { image.material.mainTexture = manager.GetUsersClrTex(); } - Tạo một
ImagehoặcRawImagetrong scene, gán hai camera và image đó vàoOverlayController, sau đó chạy thử.
Hình hiển thị có thể bị lật ngược. Có thể khắc phục bằng cách đặt Rotation.x = 180 trên image.
Đồng bộ và hiển thị mô hình
Gắn hai script AvatarController và AvatarScaler lên mô hình nhân vật.
AvatarController
- Bật
Mirrored Movement. - Bật
Vertical Movement. - Đặt
Move Rate = 1. - Đặt
Smooth Factor = 0hoặc giữ giá trị mặc định. - Gán
BackgroundCameravàoPos Relative To Camera. - Bật
Pos Rel Overlay Color.
AvatarScaler
- Bật
Mirrored Avatar. - Bật
Continuous Scaling. - Đặt
Smooth Factor = 5. - Gán
Main CameravàoForeground Camera.
Nếu kéo thả trực tiếp trong Inspector, dùng cách gán trên. Nếu muốn thiết lập bằng code, xem phần tiếp theo.
Cấu hình Canvas
- Đặt
RenderModethànhScreen Space - Camera. - Gán
BackgroundCameravàoRender Camera.
Chế độ mặc định Screen Space - Overlay thường đưa UI lên trên cùng nên có thể che mất các đối tượng 3D. Chuyển sang Screen Space - Camera để UI hiển thị theo phạm vi camera.
Đổi mẫu trang phục theo cử chỉ cơ thể
- Tạo một GameObject rỗng, đặt tên
GestureController. Tạo scriptClothingGestureListener.csđể nhận cử chỉ từ người dùng.
using UnityEngine;
using UnityEngine.UI;
public class ClothingGestureListener : MonoBehaviour, KinectGestures.GestureListenerInterface
{
[Tooltip("Chỉ số người dùng được theo dõi. 0 là người thứ nhất, 1 là người thứ hai, ...")]
public int trackedPlayer = 0;
[Tooltip("Text hiển thị thông tin cử chỉ nhận được")]
public Text gestureStatusText;
public WardrobeModelSwitcher wardrobeController;
private bool showingProgress;
public void UserDetected(long userId, int userIndex)
{
KinectManager manager = KinectManager.Instance;
if (manager == null || userIndex != trackedPlayer)
{
return;
}
manager.DetectGesture(userId, KinectGestures.Gestures.SwipeLeft);
manager.DetectGesture(userId, KinectGestures.Gestures.SwipeRight);
}
public void UserLost(long userId, int userIndex)
{
if (userIndex != trackedPlayer)
{
return;
}
}
public void GestureInProgress(long userId, int userIndex, KinectGestures.Gestures gesture,
float progress, KinectInterop.JointType joint, Vector3 screenPos)
{
if (userIndex != trackedPlayer || gestureStatusText == null)
{
return;
}
string message = null;
if ((gesture == KinectGestures.Gestures.ZoomOut || gesture == KinectGestures.Gestures.ZoomIn) && progress > 0.5f)
{
message = string.Format("{0} - {1:F0}%", gesture, screenPos.z * 100f);
}
else if ((gesture == KinectGestures.Gestures.Wheel ||
gesture == KinectGestures.Gestures.LeanLeft ||
gesture == KinectGestures.Gestures.LeanRight) && progress > 0.5f)
{
message = string.Format("{0} - {1:F0} độ", gesture, screenPos.z);
}
else if (gesture == KinectGestures.Gestures.Run && progress > 0.5f)
{
message = string.Format("{0} - tiến trình: {1:F0}%", gesture, progress * 100f);
}
if (message != null)
{
gestureStatusText.text = message;
showingProgress = true;
}
}
public bool GestureCompleted(long userId, int userIndex, KinectGestures.Gestures gesture,
KinectInterop.JointType joint, Vector3 screenPos)
{
if (userIndex != trackedPlayer)
{
return false;
}
if (gestureStatusText != null)
{
gestureStatusText.text = gesture + " đã nhận diện";
}
switch (gesture)
{
case KinectGestures.Gestures.SwipeLeft:
if (wardrobeController != null)
{
wardrobeController.OutfitIndex++;
}
break;
case KinectGestures.Gestures.SwipeRight:
if (wardrobeController != null)
{
wardrobeController.OutfitIndex--;
}
break;
}
return true;
}
public bool GestureCancelled(long userId, int userIndex, KinectGestures.Gestures gesture,
KinectInterop.JointType joint)
{
if (userIndex != trackedPlayer)
{
return false;
}
if (showingProgress)
{
showingProgress = false;
if (gestureStatusText != null)
{
gestureStatusText.text = string.Empty;
}
}
return true;
}
}
Mô hình hiển thị và bám theo chuyển động của người thật chủ yếu nhờ hai script AvatarController và AvatarScaler. Trong đó, AvatarScaler có nhiệm vụ căn kích thước mô hình theo người thật.
- Tạo một GameObject rỗng, đặt tên
WardrobeController. Tạo scriptWardrobeModelSwitcher.csđể đổi mẫu trang phục. Gán hai camera đã tạo vào các trường tương ứng trong Inspector.
using UnityEngine;
public class WardrobeModelSwitcher : MonoBehaviour
{
public Camera backgroundCamera;
public Camera mainCamera;
public GameObject[] outfits;
public int trackedPlayer = 0;
private int currentIndex = 0;
public int OutfitIndex
{
get { return currentIndex; }
set
{
if (outfits == null || outfits.Length == 0)
{
return;
}
currentIndex = value;
if (currentIndex < 0)
{
currentIndex = outfits.Length - 1;
}
else if (currentIndex >= outfits.Length)
{
currentIndex = 0;
}
SwitchOutfit(currentIndex);
}
}
public void SwitchOutfit(int targetIndex = 0)
{
if (outfits == null || outfits.Length == 0)
{
return;
}
if (targetIndex < 0 || targetIndex >= outfits.Length)
{
targetIndex = 0;
}
currentIndex = targetIndex;
for (int i = 0; i < outfits.Length; i++)
{
if (outfits[i] != null)
{
outfits[i].SetActive(i == currentIndex);
}
}
GameObject activeOutfit = outfits[currentIndex];
if (activeOutfit == null)
{
return;
}
AvatarController avatarController = activeOutfit.GetComponent<AvatarController>();
if (avatarController == null)
{
avatarController = activeOutfit.AddComponent<AvatarController>();
avatarController.playerIndex = trackedPlayer;
avatarController.mirroredMovement = true;
avatarController.verticalMovement = true;
avatarController.moveRate = 1;
avatarController.verticalOffset = 0;
avatarController.forwardOffset = 0;
avatarController.smoothFactor = 0;
}
avatarController.posRelativeToCamera = backgroundCamera;
avatarController.posRelOverlayColor = true;
KinectManager manager = KinectManager.Instance;
if (manager != null && manager.IsInitialized())
{
long userId = manager.GetUserIdByIndex(trackedPlayer);
if (userId != 0)
{
avatarController.SuccessfulCalibration(userId, false);
}
manager.avatarControllers.Clear();
MonoBehaviour[] behaviours = FindObjectsOfType<MonoBehaviour>();
foreach (MonoBehaviour behaviour in behaviours)
{
AvatarController avatar = behaviour as AvatarController;
if (avatar != null && avatar.enabled)
{
manager.avatarControllers.Add(avatar);
}
}
}
AvatarScaler avatarScaler = activeOutfit.GetComponent<AvatarScaler>();
if (avatarScaler == null)
{
avatarScaler = activeOutfit.AddComponent<AvatarScaler>();
avatarScaler.playerIndex = trackedPlayer;
avatarScaler.mirroredAvatar = true;
avatarScaler.continuousScaling = true;
avatarScaler.smoothFactor = 5;
avatarScaler.bodyScaleFactor = 1;
avatarScaler.bodyWidthFactor = 1;
avatarScaler.armScaleFactor = 1;
avatarScaler.legScaleFactor = 1;
}
avatarScaler.foregroundCamera = mainCamera;
}
}