游戏开发学习日志——细节捕捉DEMO

因为这还是一个学习过程产品,所以也仍然只是一个普通的DEMO,只有一个关卡,但是开放了部分自定义的实验性功能,可以自行设计关卡保存后给身边的人玩耍,暂时未提供关卡上传功能。

目前仅在自己的手机上做了适配测试,运行正常,但是可能游戏优化不够好,容易发热。

没有适配全面屏、水滴屏、挖空屏等等。

刘海屏:其中一个方向UI偏移,旋转后正常。

全面屏:周围黑边。(因为画面选择了最广泛的比例16:9,而我手机的比例不是,如果强行全屏会导致画面变形)

游戏玩法已经内置到游戏UI中。

游戏玩法介绍

PS:其实我在担心是不是难度大了点……我自己都没玩到90分以上。(A上面还有A+、S、SS、SSS级评定)

TIPS:多注意视角边界的物体和视角的中心点,这样子前者可以判断距离是否正确,后者可以判断方向是否正确。

Grade

V1版本修改

V1.1版本修改:

之前匹配率后面忘记增加百分号了。

1.修改设置界面文字提示。

2.修改匹配率显示格式。

 

V1.2版本修改:

1.修改了一个预置线索的视角

2.调整了评分机制

游戏开始……

开始视频预览

(部分手机端如果显示异常,如仅局部,可点击链接:查看视频

下载链接:快速捕捉V1.2 (95MB)

(https://cxbox.luheqiu.com/Game/QuickSnap/v1.2/com.LuHeQiu.QuickSnap.apk)如果直接打不开,可以复制链接到浏览器打开。

适用平台:Android

食用方式:开袋即食。

参考书籍:《Introduction to GAME DESIGN,PROTOTYPING,and DEVELOPMENT》

模型来源:《Introduction to GAME DESIGN,PROTOTYPING,and DEVELOPMENT》

开发引擎:Unity3D

引擎版本:2018.4.16f1

编程语言:C#

工程文件(包含所有数据):这个不是游戏,是制作游戏的工程数据,别下错了

云盘下载

提取码:63bf

核心代码:

这里为了在安卓上使用,做了虚拟摇杆控制移动和滑动屏幕控制视角偏转。这里也算是踩了很多坑。

一个是基于四元数控制物体旋转,这个必须搞好,不然的话就会出现我一开始的情况(x轴移动正常,但当同时上下滑动改变y轴时,因为物体本身已经发生了偏转,会导致视角的旋转,即不抱持水平)

后来的解决方案是:x轴y轴拆分,x轴移动角色对象,y轴控制摄像头仰俯角)

第二个是协同控制,一开始想当然了,没弄好多指触控识别,结果出现了使用虚拟摇杆时无法使用视角控制,使用视角控制时使用虚拟摇杆可以,但是如果松开视角控制的手会发生屏幕抖动甚至跳跃。

虚拟摇杆

使用的原理和之前那个爆破任务的弹弓原理类似,不过更为完善。主要是随触摸点移动,和范围限制(模长大于1时取其单位向量)。然后把偏转的二维向量输出,用于移动控制。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class JoystickMovement : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
#region Fields

private Image joystickAreaImg; //背景层
private Image joystickHandleImg; //浮动层
private Vector2 joystickHandleImgInitialPosition;
private Vector2 joystickInput;

[SerializeField] [Range(0.1f, 2f)] private float handleArea = 0.6f;

#endregion

#region Unity Methods

void Awake()
{
joystickAreaImg = transform.GetChild(0).GetComponent<Image>();
joystickHandleImg = joystickAreaImg.transform.GetChild(0).GetComponent<Image>();

joystickHandleImgInitialPosition = joystickHandleImg.rectTransform.anchoredPosition;
}

void OnDisable()
{
joystickInput = Vector2.zero;
joystickHandleImg.rectTransform.anchoredPosition = joystickHandleImgInitialPosition;
}

#endregion

#region Callback Events

public virtual void OnPointerDown(PointerEventData eventData)
{

OnDrag(eventData);
}

public virtual void OnDrag(PointerEventData eventData)
{
Vector2 position;

if (RectTransformUtility.ScreenPointToLocalPointInRectangle(joystickAreaImg.rectTransform,
eventData.position, eventData.pressEventCamera, out position))
{

position.x = position.x / joystickAreaImg.rectTransform.sizeDelta.x;
position.y = position.y / joystickAreaImg.rectTransform.sizeDelta.y;

joystickInput = new Vector2(position.x * 2, position.y * 2);

if (joystickInput.magnitude > 1)
{
joystickInput = joystickInput.normalized;
}

joystickHandleImg.rectTransform.anchoredPosition = new Vector2(joystickInput.x * (joystickHandleImg.rectTransform.sizeDelta.x / handleArea),
joystickInput.y * (joystickHandleImg.rectTransform.sizeDelta.y / handleArea));

}
}

public virtual void OnPointerUp(PointerEventData eventData)
{

joystickInput = Vector2.zero;
joystickHandleImg.rectTransform.anchoredPosition = joystickHandleImgInitialPosition;
}

#endregion

#region Private Methods

public float HorizontalInput()
{
return joystickInput.x;
}

public float VerticalInput()
{
return joystickInput.y;
}

#endregion
}

有了上面的函数,于是就可以……

FirstPersonController.cs部分

float speed;
GetInput(out speed);
Vector3 desiredMove = transform.forward*m_Input.y + transform.right*m_Input.x;

//这个可以不用管,是用于走路时的起伏动作的一个部分。
Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo,
m_CharacterController.height/2f, Physics.AllLayers, QueryTriggerInteraction.Ignore);
desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;

m_MoveDir.x = desiredMove.x*speed;
m_MoveDir.z = desiredMove.z*speed;
滑动控制视角

1.读取触摸点

2.如果触摸点的x轴位置在屏幕的左侧2/5,返回。

3.记录起始位置。

4.读取end到start的偏差值,基于偏差值控制视角偏转。

大概思路就是上面那样子。

 

FirstPersonController.cs部分

private void RotateView()
{

//其实是做了双端控制的准备,不过暂时只打包了Android,毕竟主要手机用的多可能。

//当初打包apk几乎快把我整吐了,每次打包到最后就是白,多的时候报一百多个error,我真的是&*%¥#@&
if(IsMobile)//是否移动端?
{
startTouchPos = Swipe.TouchStartPositionInput();
difTouchPos = Swipe.TouchDifPositionInput();
if (startTouchPos.x < Screen.width * 0.6f) return;
if (prevStartTouchPos!= startTouchPos)
{
prevStartTouchPos = startTouchPos;
prevCharactorRot = transform.localRotation;
prevCameraRot = m_Camera.transform.localRotation;
difTouchPos = Vector2.zero;
}

float xRot = difTouchPos.x * touchXSensitivity;
float yRot = difTouchPos.y * touchYSensitivity;

Quaternion m_CameraTargetRot = ClampRotationAroundXAxis(prevCameraRot * Quaternion.Euler(-yRot, 0f, 0f));//这是一条界限控制函数

transform.localRotation = prevCharactorRot * Quaternion.Euler(0f, xRot, 0f);
m_Camera.transform.localRotation = m_CameraTargetRot;

}
else
{
m_MouseLook.LookRotation(transform, m_Camera.transform);
}
}

//通过对四元数的运算,求出角度,限制仰俯角在-90°到90°之间。

Quaternion ClampRotationAroundXAxis(Quaternion q)
{
q.x /= q.w;
q.y /= q.w;
q.z /= q.w;
q.w = 1.0f;

float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan(q.x);

angleX = Mathf.Clamp(angleX, MinimumX, MaximumX);

q.x = Mathf.Tan(0.5f * Mathf.Deg2Rad * angleX);

return q;
}

SwipeManager.cs部分

private void DetectAndTriggerSwipeForTouchInput()
{
//If there is a touch
if (Input.touches.Length > 0)
{
Touch touch = Input.GetTouch(0);
for(int tempID=1; tempID<= Input.touches.Length;tempID++)
{
if (touch.position.x < 0.6f * Screen.width)
{
touch = Input.GetTouch(tempID);
}
else
{
fingerID = touch.fingerId;
break;
}
}

if (touch.phase == TouchPhase.Began)
{

//存储起始值
startPositionOfTouch = new Vector2(touch.position.x, touch.position.y);
startTimeOfTouch = Time.time;
ResetSwipeData();

}

if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
endPositionOfTouch = new Vector2(touch.position.x, touch.position.y);
endTimeOfTouch = Time.time;
UpdateSwipeData();

}

if (touch.phase == TouchPhase.Ended)
{
endPositionOfTouch = new Vector2(touch.position.x, touch.position.y);
endTimeOfTouch = Time.time;

UpdateSwipeData();

TriggerSwipes();

StartTapSequence();

}

}

}

下面就是游戏功能性代码了

TargetCamera.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.Characters.FirstPerson;

public class TargetCamera : MonoBehaviour
{
static public TargetCamera S;

static public bool editMode = false;
public GameObject firstPersonCamera;
public TextAsset shotXML;

public float maxPosDeviation = 1f;
public float maxTarDeviation = 0.5f;
public string deviationEasing = Easing.Out;
public float passingAccuracy = 0.7f;
public bool checkToDeletePlayePrefs = false;

public bool _______________________________;
public int shotNum;
public Text shotCounter, shotRating;
public Image checkMark;
public Image fpcShutterClick;
public Image tcShutterClick;
public Shot lastShot;
public int numShots;
public Shot[] playerShots;
public float[] playerRatings;
public bool[] playerShotsPassed;
public int playerShotedNum;
public int grade;

private bool isWin=false;

private void Awake()
{
S = this;
}
private void Start()
{
GameObject go = GameObject.Find("TC_ShotCounter");
shotCounter = go.GetComponent<Text>();
go = GameObject.Find("TC_ShotRating");
shotRating = go.GetComponent<Text>();
go = GameObject.Find("TC_Check");
checkMark = go.GetComponent<Image>();
go = GameObject.Find("FPC_Shutter_Click");
fpcShutterClick = go.GetComponent<Image>();
go = GameObject.Find("TC_Shutter_Click");
tcShutterClick = go.GetComponent<Image>();

//初始化
checkMark.enabled = false;
fpcShutterClick.enabled = false;
tcShutterClick.enabled = false;

Shot.LoadShot(shotXML.text);
if (Shot.shots.Count > 0)
{
shotNum = 0;
ResetPlayerShotsAndRatings();
ShowShot(Shot.shots[shotNum]);
}
}

private void ResetPlayerShotsAndRatings()
{
numShots = Shot.shots.Count;
//初始化
playerShots = new Shot[numShots];
playerRatings = new float[numShots];
playerShotsPassed = new bool[numShots];
playerShotedNum = 0;
grade = 0;
}

private void Update()
{
Shot sh;

//编辑模式
if(editMode && !FirstPersonController.IsMobile)
{
if ((Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)))
{
sh = new Shot();

sh.position = firstPersonCamera.transform.position;
sh.rotation = firstPersonCamera.transform.rotation;

//检测摄像机视角图像
Ray ray = new Ray(sh.position, firstPersonCamera.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
sh.target = hit.point;
}

if (Input.GetMouseButtonDown(0))//添加
{
Shot.shots.Add(sh);
shotNum = Shot.shots.Count - 1;
ShowShot(Shot.shots[shotNum]);
}
else if (Input.GetMouseButtonDown(1))//替换
{
Shot.ReplaceShot(shotNum, sh);
ShowShot(Shot.shots[shotNum]);
}

//ShowShot(sh);
Utils.tr(sh.ToXML());
//编辑shot时重置玩家信息
ResetPlayerShotsAndRatings();

}

if (Input.GetKeyDown(KeyCode.Q))
{
shotNum--;
if (shotNum < 0) shotNum = Shot.shots.Count - 1;
ShowShot(Shot.shots[shotNum]);
}

if (Input.GetKeyDown(KeyCode.E))
{
shotNum++;
if (shotNum >= Shot.shots.Count) shotNum = 0;
ShowShot(Shot.shots[shotNum]);
}

if (Input.GetKey(KeyCode.LeftControl))
{
if (Input.GetKeyDown(KeyCode.S))
{
Shot.SaveShots();
}
if (Input.GetKeyDown(KeyCode.X))
{
Utils.tr(Shot.XML);
}
}
}

//更新UI
shotCounter.text = (shotNum + 1).ToString() + " of " + Shot.shots.Count;
if (Shot.shots.Count == 0) { shotCounter.text = "Null"; shotNum = 0; }
//shotRating.text = "";
if(playerRatings.Length > shotNum && playerShots[shotNum] != null)
{
float rating = Mathf.Round(playerRatings[shotNum] * 100f);
if (rating < 0) rating = 0;
shotRating.text = rating.ToString() + "%";
checkMark.enabled = (playerRatings[shotNum] > passingAccuracy);
playerShotsPassed[shotNum]= (playerRatings[shotNum] > passingAccuracy);
}
else
{
shotRating.text = "";
checkMark.enabled = false;
}

//胜利判定
int passedNum=0;
foreach(bool tb in playerShotsPassed)
{
if (tb) passedNum += 1;
}
if (passedNum >= numShots && !isWin)
{
Invoke("WinOver", 2f);
isWin = true;
}
}

public void WinOver()
{
WelcomeUI.S.YouWin(playerShotedNum, playerRatings);
}

//按下快门
public void ShutterPressed()
{
Shot sh;

if (editMode)
{
sh = new Shot();

sh.position = firstPersonCamera.transform.position;
sh.rotation = firstPersonCamera.transform.rotation;

//检测摄像机视角图像
Ray ray = new Ray(sh.position, firstPersonCamera.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
sh.target = hit.point;
}

Shot.shots.Add(sh);
shotNum = Shot.shots.Count - 1;
ShowShot(Shot.shots[shotNum]);

//ShowShot(sh);
Utils.tr(sh.ToXML());
//编辑shot时重置玩家信息
ResetPlayerShotsAndRatings();
}
else
{
playerShotedNum++;

sh = new Shot();

sh.position = firstPersonCamera.transform.position;
sh.rotation = firstPersonCamera.transform.rotation;

//检测摄像机视角图像
Ray ray = new Ray(sh.position, firstPersonCamera.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
sh.target = hit.point;
}

float acc = Shot.Compare(Shot.shots[shotNum], sh);
lastShot = sh;
playerShots[shotNum] = sh;
playerRatings[shotNum] = acc;
StartCoroutine(ClickWhiteOnFPC());
ShowShot(sh);
Invoke("ShowCurrentShot", 1f);
this.GetComponent<AudioSource>().Play();

}
}

public void LastPressed()
{
shotNum--;
if (shotNum < 0) shotNum = Shot.shots.Count - 1;
ShowShot(Shot.shots[shotNum]);
}
public void NextPressed()
{
shotNum++;
if (shotNum >= Shot.shots.Count) shotNum = 0;
ShowShot(Shot.shots[shotNum]);
}

public void ResetShotOnMobile()
{
Shot sh;

sh = new Shot();

sh.position = firstPersonCamera.transform.position;
sh.rotation = firstPersonCamera.transform.rotation;

//检测摄像机视角图像
Ray ray = new Ray(sh.position, firstPersonCamera.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
sh.target = hit.point;
}

Shot.ReplaceShot(shotNum, sh);
ShowShot(Shot.shots[shotNum]);

}

public void SaveShotOnMobile()
{
Shot.SaveShots();
}

public void ShowShot(Shot sh)
{
//定位
transform.position = sh.position;
transform.rotation = sh.rotation;
}

public void ShowCurrentShot()
{
StartCoroutine(ClickWhiteOnTC());
ShowShot(Shot.shots[shotNum]);
}

//协程
public IEnumerator ClickWhiteOnFPC()
{
fpcShutterClick.enabled = true;
yield return new WaitForSeconds(0.05f);
fpcShutterClick.enabled = false;
}

public IEnumerator ClickWhiteOnTC()
{
tcShutterClick.enabled = true;
yield return new WaitForSeconds(0.05f);
tcShutterClick.enabled = false;
}

public void OnDrawGizmos()
{
List<Shot> shots = Shot.shots;
for (int i=0;i<shots.Count;i++)
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(shots[i].position, 0.5f);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(shots[i].position, shots[i].target);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(shots[i].target, 0.25f);
}

if (checkToDeletePlayePrefs)
{
Shot.DeleteShots();
checkToDeletePlayePrefs = false;
shotNum = 0;
}
if(lastShot != null)
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(lastShot.position, 0.25f);
Gizmos.color = Color.white;
Gizmos.DrawLine(lastShot.position, lastShot.target);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(lastShot.target, 0.125f);
}
}
}
Shots.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Shot
{
static public List<Shot> shots = new List<Shot>() ;
static public string prefsName = "QuickSnap_Shots";

public Vector3 position;
public Quaternion rotation;
public Vector3 target;

//XML载入预处理
public string ToXML()
{
string ss = "<shot ";
ss += "x=\"" + position.x + "\" ";
ss += "y=\"" + position.y + "\" ";
ss += "z=\"" + position.z + "\" ";
ss += "qx=\"" + rotation.x + "\" ";
ss += "qy=\"" + rotation.y + "\" ";
ss += "qz=\"" + rotation.z + "\" ";
ss += "qw=\"" + rotation.w + "\" ";
ss += "tx=\"" + target.x + "\" ";
ss += "ty=\"" + target.y + "\" ";
ss += "tz=\"" + target.z + "\" ";
ss += " />";

return (ss);
}

//XML解析调用
static public Shot parseShotXML(PT_XMLHashtable xHT)
{
Shot sh = new Shot();

sh.position.x = float.Parse(xHT.att("x"));
sh.position.y = float.Parse(xHT.att("y"));
sh.position.z = float.Parse(xHT.att("z"));
sh.rotation.x = float.Parse(xHT.att("qx"));
sh.rotation.y = float.Parse(xHT.att("qy"));
sh.rotation.z = float.Parse(xHT.att("qz"));
sh.rotation.w = float.Parse(xHT.att("qw"));
sh.target.x = float.Parse(xHT.att("tx"));
sh.target.y = float.Parse(xHT.att("ty"));
sh.target.z = float.Parse(xHT.att("tz"));

return (sh);
}

//加载所有Shot
static public void LoadShot(string shotXMLText="")
{
//清空List
shots = new List<Shot>();

//读取XML并解析
PT_XMLReader xmlr = new PT_XMLReader();
if (PlayerPrefs.HasKey(prefsName))
{
shotXMLText = PlayerPrefs.GetString(prefsName);
}

xmlr.Parse(shotXMLText);

//解析所有<shot>,添加到List
PT_XMLHashList hl = xmlr.xml["xml"][0]["shot"];
for(int i = 0; i < hl.Count; i++)
{
PT_XMLHashtable ht = hl[i];
Shot sh = parseShotXML(ht);

shots.Add(sh);
}

}

//保存shots
static public void SaveShots()
{
string xs = Shot.XML;

Utils.tr(xs);

PlayerPrefs.SetString(prefsName, xs);

Utils.tr("PlayerPrefs." + prefsName + " has been set.");
}

static public string XML
{
get
{
string xs = "<xml>\n";
foreach(Shot sh in shots)
{
xs += sh.ToXML() + "\n";
}
xs += "</xml>";
return (xs);
}
}

//shot删除(PlayPrefs)
static public void DeleteShots()
{
shots = new List<Shot>();
if (PlayerPrefs.HasKey(prefsName))
{
PlayerPrefs.DeleteKey(prefsName);
Utils.tr("PlayerPrefs." + prefsName + " has been deleted.");
}
else
{
Utils.tr("There was no PlayerPrefs." + prefsName + "to delete.");
}
}

//shot替换(PlayPrefs)
static public void ReplaceShot(int ndx, Shot sh)
{
if (shots == null || shots.Count <= ndx) return;
shots.RemoveAt(ndx);
shots.Insert(ndx, sh);

Utils.tr("Replaced shot:", ndx, "with", sh.ToString());
}

//shot比较
static public float Compare(Shot target ,Shot test)
{
float posDev = (test.position - target.position).magnitude;
float tarDev = (test.target - target.target).magnitude;

float posAccPct, tarAccPct, posAP2, tarAP2;
TargetCamera tc = TargetCamera.S;

posAccPct = 1 - (posDev / tc.maxPosDeviation);
tarAccPct = 1 - (tarDev / tc.maxTarDeviation);

posAP2 = Easing.Ease(posAccPct, tc.deviationEasing);
tarAP2 = Easing.Ease(tarAccPct, tc.deviationEasing);

float accuracy = (posAP2 + tarAP2) / 2f;

string accText = Utils.RoundToPlaces(accuracy * 100).ToString() + "%";
Utils.tr("Position:", posAccPct, posAP2, "Target:", tarAccPct, tarAP2, "Accuracy:", accText);

return (accuracy);
}
}
WelcomeUI.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.Characters.FirstPerson;

public class WelcomeUI : MonoBehaviour
{
#region GameField
public static WelcomeUI S;

public GameObject fPSController;
public GameObject fPSCamera;
public GameObject targerCamera;
public GameObject fPC;
public GameObject tC;
public GameObject swipe;
public GameObject joystick;
public GameObject buttonUI;
public GameObject welcomeCamera;
public GameObject welcomeInterface;
public GameObject quickSnap;
public GameObject starGame;
public GameObject continueGame;
public GameObject gameIntroduction;
public GameObject gameSettings;
public GameObject intro_Title;
public GameObject intro_Content;
public GameObject intro_Image;
public GameObject intro_Point;
public GameObject set_Title;
public GameObject set_Content;
public Slider set_Sensitivity;
public Slider set_WalkSpeed;
public Toggle set_EditMode;
public GameObject set_ShotReset;
public GameObject back;

public GameObject win_Title;
public GameObject win_Content;
public GameObject win_Degree;
public GameObject win_Grade;

public GameObject edit_ReShutter;
public GameObject edit_ReSave;

[SerializeField] private Vector3 welcomeLocalPos;
[SerializeField] private Vector3 startLocalPos;

[SerializeField] private Quaternion welcomeLocalRot;
[SerializeField] private Quaternion startLocalRot;

private bool isStart= false;
private bool isMoving = false;
private bool isStarted = false;
private bool isStartOver = false;

private bool isYouWin = false;
private bool isReturning = false;
private bool isReturned = false;
private bool isReturnOver = false;

private float timeStart;
private float timeDuration = 3.5f;

private Vector3 startCamPos;
private Quaternion startCamRot;

public string tempS="";
public string tempDegree = "";

#endregion
private void Awake()
{
S = this;
}

public void Start()
{
set_Sensitivity.value = 4.3f;
set_WalkSpeed.value = 5;
}

public void Update()
{
if (!isStartOver)
{
if (isStart)
{
isStart = false;
isMoving = true;

timeStart = Time.time;
}

if (isMoving && !isStarted)
{
float u = (Time.time - timeStart) / timeDuration;
if (u >= 1)
{
u = 1;
isMoving = false;
isStarted = true;
}
u = u - 0.2f * Mathf.Sin(2 * Mathf.PI * u); //缓动函数

welcomeCamera.transform.position = (1 - u) * welcomeLocalPos + u * startLocalPos;
welcomeCamera.transform.rotation = Quaternion.Slerp(welcomeLocalRot, startLocalRot, u);
}
if (isStarted)
{
welcomeCamera.SetActive(false);

fPSController.SetActive(true);
targerCamera.SetActive(true);
fPC.SetActive(true);
tC.SetActive(true);
swipe.SetActive(true);
joystick.SetActive(true);
buttonUI.SetActive(true);

isStarted = false;
isStartOver = true;
}
}

if (!isReturnOver)
{
if (isYouWin)
{
fPSController.SetActive(false);
targerCamera.SetActive(false);
fPC.SetActive(false);
tC.SetActive(false);
swipe.SetActive(false);
joystick.SetActive(false);
buttonUI.SetActive(false);

welcomeCamera.SetActive(true);

isYouWin = false;
isReturning = true;

timeStart = Time.time;
startCamPos = fPSCamera.transform.position;
startCamRot = fPSCamera.transform.rotation;
welcomeCamera.transform.position = startCamPos;
welcomeCamera.transform.rotation = startCamRot;
}

if (isReturning && !isReturned)
{
float u = (Time.time - timeStart) / timeDuration;
if (u >= 1)
{
u = 1;
isReturning = false;
isReturned = true;
}
u = u - 0.2f * Mathf.Sin(2 * Mathf.PI * u); //缓动函数

welcomeCamera.transform.position = (1 - u) * startCamPos + u * welcomeLocalPos;
welcomeCamera.transform.rotation = Quaternion.Slerp(startCamRot, welcomeLocalRot, u);
}
if (isReturned)
{
welcomeInterface.SetActive(true);
win_Title.SetActive(true);
win_Content.SetActive(true);
win_Degree.SetActive(true);
win_Grade.SetActive(true);

win_Grade.GetComponent<Text>().text = tempS.Replace('T', '\n');
win_Degree.GetComponent<Text>().text = tempDegree;

isReturnOver = true;
}
}
}

public void StartGame()
{
quickSnap.SetActive(false);
starGame.SetActive(false);
continueGame.SetActive(false);
gameIntroduction.SetActive(false);
gameSettings.SetActive(false);

welcomeInterface.SetActive(false);
isStart = true;
}

public void ContinueGame()
{
quickSnap.SetActive(false);
starGame.SetActive(false);
continueGame.SetActive(false);
gameIntroduction.SetActive(false);
gameSettings.SetActive(false);
welcomeInterface.SetActive(false);

fPC.SetActive(true);
swipe.SetActive(true);

}
public void GameIntroduction()
{
quickSnap.SetActive(false);
starGame.SetActive(false);
continueGame.SetActive(false);
gameIntroduction.SetActive(false);
gameSettings.SetActive(false);

intro_Title.SetActive(true);
intro_Content.SetActive(true);
intro_Image.SetActive(true);
intro_Point.SetActive(true);
back.SetActive(true);
}

public void GameSettings()
{
quickSnap.SetActive(false);
starGame.SetActive(false);
continueGame.SetActive(false);
gameIntroduction.SetActive(false);
gameSettings.SetActive(false);

set_Title.SetActive(true);
set_Content.SetActive(true);
set_Sensitivity.gameObject.SetActive(true);
set_WalkSpeed.gameObject.SetActive(true);
set_EditMode.gameObject.SetActive(true);
set_ShotReset.SetActive(true);
back.SetActive(true);
}

public void GameMenuBack()
{
fPC.SetActive(false);
swipe.SetActive(false);

intro_Title.SetActive(false);
intro_Content.SetActive(false);
intro_Image.SetActive(false);
intro_Point.SetActive(false);

set_Title.SetActive(false);
set_Content.SetActive(false);
set_Sensitivity.gameObject.SetActive(false);
set_WalkSpeed.gameObject.SetActive(false);
set_EditMode.gameObject.SetActive(false);
set_ShotReset.SetActive(false);

back.SetActive(false);

welcomeInterface.SetActive(true);

quickSnap.SetActive(true);
if (isStartOver) continueGame.SetActive(true); else starGame.SetActive(true);
gameIntroduction.SetActive(true);
gameSettings.SetActive(true);
}

public void SetSensivity()
{
double value = 0.0145 * Mathf.Exp(set_Sensitivity.value * 0.45f);
FirstPersonController.touchXSensitivity = (float)value;
FirstPersonController.touchYSensitivity = (float)value;
}

public void SetWalkSpeed()
{
FirstPersonController.m_WalkSpeed = set_WalkSpeed.value;
}

public void EditModeSetOnMobile()
{
if (set_EditMode.isOn)
{
TargetCamera.editMode = true;
edit_ReShutter.SetActive(true);
edit_ReSave.SetActive(true);
}
else
{
TargetCamera.editMode = false;
edit_ReShutter.SetActive(false);
edit_ReShutter.SetActive(false);
}
}

public void ShotPrefsResrt()
{
Shot.DeleteShots();
}

public void YouWin(int playerShotedNum, float[] playerRatings)
{
float AveRating = 0f;
foreach (float rating in playerRatings)
{
AveRating += rating;
}
AveRating = Mathf.Round(AveRating / playerRatings.Length * 100f);

int AddPoints = 0;
if (playerShotedNum < 16) AddPoints = 16 - playerShotedNum;
else if (playerShotedNum > 24) AddPoints = 24 - playerShotedNum;
int Grade = 100 - (int)((100 - AveRating) * (1.33f)) + AddPoints;
if (Grade >= 100) Grade = 100;
else if (Grade <= 0) Grade = 0;
tempS = "胶卷消耗数:" + playerShotedNum + "T综合匹配率:" + AveRating + "T结算总得分:" + Grade;

tempDegree="D-";
if (Grade >= 98) tempDegree = "SSS";
else if (Grade >= 96) tempDegree = "SS";
else if (Grade >= 93) tempDegree = "S";
else if (Grade >= 90) tempDegree = "A+";
else if (Grade >= 87) tempDegree = "A";
else if (Grade >= 85) tempDegree = "A-";
else if (Grade >= 82) tempDegree = "B+";
else if (Grade >= 79) tempDegree = "B";
else if (Grade >= 76) tempDegree = "B-";
else if (Grade >= 73) tempDegree = "C+";
else if (Grade >= 70) tempDegree = "C";
else if (Grade >= 67) tempDegree = "C-";
else if (Grade >= 64) tempDegree = "D+";
else if (Grade >= 62) tempDegree = "D";
else if (Grade >= 60) tempDegree = "D-";
else if (Grade < 60) tempDegree = "?";
else if (Grade < 50) tempDegree = "??";
else if (Grade < 40) tempDegree = "???";

isYouWin = true;
}
}
这个是八个镜头的对比数据
<xml>
  <shot x="-17.312" y="1.78" z="6.512172" qx="-0.003993143" qy="-0.9950927" qz="0.04518745" qw="-0.08793474" tx="-15.84644" ty="1.019435" tz="-1.715417"  />
  <shot x="-21.90255" y="1.78" z="29.87937" qx="0.04885036" qy="0.003486181" qz="-0.0001705058" qw="0.9988" tx="-21.87488" ty="1.391284" tz="33.84363"  />
  <shot x="-24.88841" y="1.78" z="1.778479" qx="0.01991105" qy="0.1261734" qz="-0.002533002" qw="0.9918052" tx="-24.07588" ty="1.649649" tz="4.920304"  />
  <shot x="-2.820553" y="1.78" z="23.37497" qx="0.06876711" qy="0.9218622" qz="-0.1925887" qw="0.3291668" tx="-0.2400206" ty="0" tz="20.22217"  />
  <shot x="-17.90158" y="1.78" z="42.33155" qx="0.1302008" qy="0.2338618" qz="0.03161911" qw="-0.9629936" tx="-19.10048" ty="2.500004" tz="44.65438"  />
  <shot x="-30.00804" y="1.78" z="31.57938" qx="-0.1287968" qy="0.0008646704" qz="-0.0001123022" qw="-0.9916706" tx="-30.01056" ty="1.398686" tz="33.02258"  />
  <shot x="-2.918861" y="1.78" z="5.072468" qx="-0.1221666" qy="-0.6711882" qz="0.1135243" qw="-0.7222838" tx="-1.56189" ty="1.306174" tz="5.172117"  />
  <shot x="-6.68367" y="1.78" z="30.49959" qx="-0.01134583" qy="0.01308868" qz="-0.0001485241" qw="-0.99985" tx="-6.747552" ty="1.724607" tz="32.93919"  />
</xml>
点赞

发表评论

昵称和uid可以选填一个,邮箱必填(用于评论被回复时的邮件提醒)
tips:输入uid可以获取你的B站昵称和头像