2021-03-22 19:20:51 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using Mapbox.Unity.Map;
|
|
|
|
|
|
using Mapbox.Utils;
|
2021-03-23 16:07:31 +08:00
|
|
|
|
using Assets.Scripts.Apis.Models;
|
|
|
|
|
|
using static Assets.Scripts.Apis.Models.MapDataModel;
|
2021-03-25 16:22:09 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using Random = UnityEngine.Random;
|
|
|
|
|
|
using Assets.Scripts.Apis;
|
|
|
|
|
|
using GeoJSON.Net.Geometry;
|
|
|
|
|
|
using TurfCS;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Collections.Generic;
|
2021-03-22 19:20:51 +08:00
|
|
|
|
|
2021-03-23 16:07:31 +08:00
|
|
|
|
namespace Assets.Scenes.Ride.Scripts
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
|
|
|
|
|
public class PlayerController : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
[Header("Character")]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
GameObject character;
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
Animator characterAnimator;
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
AbstractMap map;
|
|
|
|
|
|
|
2021-03-25 16:22:09 +08:00
|
|
|
|
#region 动画控制参数
|
|
|
|
|
|
Vector3 nextPos;
|
2021-03-23 16:07:31 +08:00
|
|
|
|
Vector3 prePos;
|
2021-03-25 16:22:09 +08:00
|
|
|
|
Vector2d currentlatlong; //当前坐标
|
|
|
|
|
|
Vector2d nextlatlong; //下一个点的坐标
|
|
|
|
|
|
float timer = 1.0f;//计时器
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 选手骑行数据
|
|
|
|
|
|
bool isStart;
|
|
|
|
|
|
MapDataModel mapData;
|
|
|
|
|
|
int userId;
|
|
|
|
|
|
|
|
|
|
|
|
double speed;
|
|
|
|
|
|
double power;
|
|
|
|
|
|
double gradev;
|
|
|
|
|
|
double elevation;
|
|
|
|
|
|
double cadance;
|
|
|
|
|
|
double heartRate;
|
|
|
|
|
|
int ticks;
|
|
|
|
|
|
double totalDistance;
|
|
|
|
|
|
double currentSlope;
|
|
|
|
|
|
double nextSlope;
|
|
|
|
|
|
double nextSlopeDistance;
|
|
|
|
|
|
double distance;
|
|
|
|
|
|
|
|
|
|
|
|
public int UserId { get => userId; }
|
|
|
|
|
|
public bool IsStart { get => isStart; }
|
|
|
|
|
|
public double Speed { get => speed; }
|
|
|
|
|
|
public double Power { get => power; }
|
|
|
|
|
|
public double Cadance { get => cadance; }
|
|
|
|
|
|
public double HeartRate { get => heartRate; }
|
|
|
|
|
|
public int TotalTicks { get => ticks; }
|
|
|
|
|
|
public double TotalDistance { get => totalDistance; }
|
|
|
|
|
|
public double CurrentSlope { get => currentSlope; }
|
|
|
|
|
|
public double NextSlope { get => nextSlope;}
|
|
|
|
|
|
public double NextSlopeDistance { get => nextSlopeDistance; }
|
|
|
|
|
|
public double Gradev { get => gradev; }
|
|
|
|
|
|
public double Elevation { get => elevation; }
|
|
|
|
|
|
#endregion
|
2021-03-22 19:20:51 +08:00
|
|
|
|
|
|
|
|
|
|
void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
characterAnimator = GetComponentInChildren<Animator>();
|
2021-03-25 16:22:09 +08:00
|
|
|
|
var mainController = transform.parent.GetComponent<MainController>();
|
|
|
|
|
|
mapData = mainController.GetMapData();//获取路书信息
|
|
|
|
|
|
InitializePlayer(mainController.GetCenterCoordinate());//初始人物
|
2021-03-23 16:07:31 +08:00
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
|
2021-03-22 19:20:51 +08:00
|
|
|
|
void Update()
|
|
|
|
|
|
{
|
2021-03-23 16:07:31 +08:00
|
|
|
|
timer -= Time.deltaTime;
|
2021-03-25 16:22:09 +08:00
|
|
|
|
if (timer <= 0)//定时器 一秒执行一次
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
Run();
|
2021-03-23 16:07:31 +08:00
|
|
|
|
timer = 1.0f;
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
2021-03-23 16:07:31 +08:00
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
|
|
|
|
|
|
#region 骑行逻辑
|
|
|
|
|
|
//当前人物骑行状态 true 开始 false 暂停
|
|
|
|
|
|
public void SetStart(bool start)
|
2021-03-23 16:07:31 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
isStart = start;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//初始化玩家距离/朝向
|
|
|
|
|
|
void InitializePlayer(double[] coordinates)
|
|
|
|
|
|
{
|
|
|
|
|
|
ticks = 0;//当前骑行时间
|
|
|
|
|
|
//初始化人物位置
|
|
|
|
|
|
totalDistance = 10;//TODO:根据骑行模式动态取值
|
|
|
|
|
|
currentlatlong = Along(totalDistance);//new Vector2d(coordinates[0], coordinates[1]);//当前坐标
|
|
|
|
|
|
nextlatlong = currentlatlong;//下一秒坐标
|
|
|
|
|
|
////初始化人物转向
|
|
|
|
|
|
//var secondPlace = mapData.List[10].Point;
|
|
|
|
|
|
//var secondVect3d = map.GeoToWorldPosition( new Vector2d(secondPlace[0], secondPlace[1]));
|
|
|
|
|
|
//Quaternion firstRotation = Quaternion.LookRotation(transform.localPosition - secondVect3d);
|
|
|
|
|
|
//character.transform.rotation = Quaternion.Euler(0, firstRotation.eulerAngles.y, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
//骑行中
|
|
|
|
|
|
void Run()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsStart)
|
|
|
|
|
|
{
|
|
|
|
|
|
//CamControl();
|
|
|
|
|
|
ComputeMapData();//计算海拔&坡度&下一个点信息
|
|
|
|
|
|
power = 300;//功率
|
|
|
|
|
|
speed = Helper.CalculateSpeed(elevation, gradev, power, 65, 7);
|
|
|
|
|
|
distance = Math.Round(speed / 3600, 5);
|
|
|
|
|
|
totalDistance += distance;
|
|
|
|
|
|
characterAnimator.SetBool("IsRide", false);//初始化动画状态
|
|
|
|
|
|
if (totalDistance <= mapData.TotalDistance)
|
|
|
|
|
|
{
|
|
|
|
|
|
ticks++;
|
|
|
|
|
|
if (distance > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
characterAnimator.SetBool("IsRide", true);//开始移动动画
|
|
|
|
|
|
nextlatlong = Along(totalDistance);//下一个坐标
|
|
|
|
|
|
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
|
|
|
|
|
|
prePos = transform.localPosition;//当前点
|
|
|
|
|
|
|
|
|
|
|
|
StartCoroutine(LookAtNextPos());//转向
|
|
|
|
|
|
StartCoroutine(MoveTo());//移动
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
//TODO保存骑行数据
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
characterAnimator.SetBool("IsRide", false);
|
|
|
|
|
|
}
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
2021-03-23 16:07:31 +08:00
|
|
|
|
|
2021-03-25 16:22:09 +08:00
|
|
|
|
//TODO:骑行结束
|
|
|
|
|
|
void Finish()
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
//MapInterruptRecordApi api = new MapInterruptRecordApi();
|
|
|
|
|
|
|
|
|
|
|
|
//api.Add(null, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 工具类
|
|
|
|
|
|
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
|
|
|
|
|
|
void ComputeMapData()
|
|
|
|
|
|
{
|
|
|
|
|
|
double sumDistance = 0;
|
|
|
|
|
|
var pointList = mapData.List;
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
for (int i = 0; i < pointList.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sumDistance += pointList[i].Distance;
|
|
|
|
|
|
if (totalDistance >= sumDistance)
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
index = i;
|
|
|
|
|
|
break;
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
//计算当前海拔和坡度
|
|
|
|
|
|
elevation = pointList[index].Elevation;
|
|
|
|
|
|
gradev = pointList[index].Grade;
|
|
|
|
|
|
//计算下一个点的坡度和距离
|
|
|
|
|
|
int nextIndex = index == pointList.Count - 1 ? index : index + 1;
|
|
|
|
|
|
nextSlope = pointList[nextIndex].Grade;
|
|
|
|
|
|
nextSlopeDistance = sumDistance + pointList[nextIndex].Distance - totalDistance;
|
2021-03-23 16:07:31 +08:00
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
//根据距离计算坐标
|
|
|
|
|
|
Vector2d Along(double endDistance)
|
2021-03-23 16:07:31 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
if (mapData != null)
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
2021-03-25 16:22:09 +08:00
|
|
|
|
var list = mapData.List.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p.Point[0], p.Point[1]));
|
|
|
|
|
|
LineString lineString = new LineString(list);
|
|
|
|
|
|
var pt1 = Turf.Along(lineString, endDistance);
|
|
|
|
|
|
var ll = ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates);
|
|
|
|
|
|
return new Vector2d(ll.Latitude, ll.Longitude);
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
return nextlatlong;
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 人物移动与转向控制
|
|
|
|
|
|
IEnumerator LookAtNextPos()
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
2021-03-23 16:07:31 +08:00
|
|
|
|
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
|
2021-03-22 19:20:51 +08:00
|
|
|
|
Quaternion thisRotation = character.transform.localRotation;
|
|
|
|
|
|
|
|
|
|
|
|
float t = 0;
|
|
|
|
|
|
while (t < 1.0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
t += Time.deltaTime / 0.25f;
|
|
|
|
|
|
var rotationValue = Quaternion.Slerp(thisRotation, neededRotation, t);
|
|
|
|
|
|
character.transform.rotation = Quaternion.Euler(0, rotationValue.eulerAngles.y, 0);
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-25 16:22:09 +08:00
|
|
|
|
|
|
|
|
|
|
//人物移动控制
|
|
|
|
|
|
IEnumerator MoveTo()
|
|
|
|
|
|
{
|
|
|
|
|
|
//让人物移动分点增加动画的流畅度
|
|
|
|
|
|
float t = 0;
|
|
|
|
|
|
while (t < 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
t += Time.deltaTime;
|
|
|
|
|
|
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
|
|
|
|
|
|
transform.localPosition = v;
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-22 19:20:51 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2021-03-25 16:22:09 +08:00
|
|
|
|
#region 相机控制
|
2021-03-22 19:20:51 +08:00
|
|
|
|
[Header("CameraSettings")]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
Camera cam;
|
|
|
|
|
|
Vector3 previousPos = Vector3.zero;
|
|
|
|
|
|
Vector3 deltaPos = Vector3.zero;
|
|
|
|
|
|
|
2021-03-25 16:22:09 +08:00
|
|
|
|
IEnumerator CamControl()//TODO 替换成cinemachine
|
2021-03-22 19:20:51 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (cam != null)
|
|
|
|
|
|
{
|
2021-03-23 16:07:31 +08:00
|
|
|
|
float t = 0;
|
|
|
|
|
|
while (t < 1.0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
t += Time.deltaTime / 0.5f;
|
|
|
|
|
|
deltaPos = transform.position - previousPos;
|
|
|
|
|
|
//deltaPos.y = 0;
|
|
|
|
|
|
cam.transform.position = Vector3.Lerp(cam.transform.position, cam.transform.position + deltaPos, t);
|
|
|
|
|
|
previousPos = transform.position;
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
2021-03-22 19:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|