新增人物控制器抽象类

This commit is contained in:
lishuo 2021-04-01 11:01:29 +08:00
parent eb93577d68
commit 2e6338bcf3
5 changed files with 321 additions and 485 deletions

View File

@ -0,0 +1,255 @@
using Assets.Scripts.Apis.Models;
using GeoJSON.Net.Geometry;
using Mapbox.Unity.Map;
using Mapbox.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TurfCS;
using UnityEngine;
namespace Assets.Scenes.Ride.Scripts
{
public abstract class AbstractPlayer: MonoBehaviour
{
[Header("Character")]
[SerializeField]
GameObject character;
[SerializeField]
Animator characterAnimator;
AbstractMap map;
#region
Vector3 nextPos;
Vector3 prePos;
float timer = 1.0f;//计时器
#endregion
#region
protected Vector2d nextlatlong; //下一个点的坐标
protected bool isStart;//开始或者暂停
protected bool isQuit;//true 中途退出 或者到达终点
protected bool isMajor;//是否是主人公
protected MapDataModel mapData;
protected int userId;
protected DateTime startTime;//开始骑行时间
protected DateTime endTime;//结束骑行时间
protected double weight;//体重
protected double bicycleWeight;//车重
protected double speed;
protected double power;
protected double elevation;
protected double cadance;
protected int heartRate;
protected int ticks;
protected double totalDistance;
protected double currentSlope;
protected double nextSlope;
protected double nextSlopeDistance;
protected double distance;
protected double currentSlopeDistance;
protected double lastEndDistance;
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 CurrentSlopeDistance { get => currentSlopeDistance; }
public double Elevation { get => elevation; }
public double LastEndDistance { get => lastEndDistance; }
#endregion
#region
//开始骑行
public void SetStart()
{
isStart = true;
startTime = DateTime.Now;
}
//继续骑行
public void SetContinue()
{
isStart = true;
}
//暂停骑行
public void SetPause()
{
isStart = false;
}
//退出或者完成骑行
public void SetQuit()
{
isQuit = true;
endTime.AddSeconds(ticks);//计算结束时间
}
#endregion
void Start()
{
Init();
}
void Update()
{
Excute();
}
#region
//初始化骑行数据
protected virtual void Init()
{
characterAnimator = GetComponentInChildren<Animator>();
var mainController = transform.parent.GetComponent<CyclingController>();
map = FindObjectOfType<AbstractMap>();
mapData = mainController.GetMapData();//获取路书信息
nextlatlong = new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]);//初始化人物位置 TODO加上之前骑行距离
}
protected virtual void Excute()
{
timer -= Time.deltaTime;
if (timer <= 0)//定时器 一秒执行一次
{
Run();
timer = 1.0f;
}
}
//骑行中
protected virtual void Run()
{
ComputeNextSlope();//计算下一个坡度相关数据
if (isStart)
{
ticks++;
Compute();//接受蓝牙设备数据计算
characterAnimator.SetBool("IsRide", false);//初始化动画状态
if (totalDistance <= mapData.TotalDistance)
{
//数据处理
nextlatlong = Along(totalDistance);//下一个坐标
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
nextPos.y += 0.3f;//提高y轴让人物站在地图上面
prePos = transform.localPosition;//当前点
//动画控制
if (distance > 0)
{
characterAnimator.SetBool("IsRide", true);//开始移动动画
StartCoroutine(LookAtNextPos());//转向
StartCoroutine(MoveTo());//移动
}
}
else
{
totalDistance = mapData.TotalDistance;
characterAnimator.SetBool("ReachEnd", true);//到达终点
Task.Run(() => { Upload(); });//异步上传数据
isStart = false;
isQuit = true;
}
}
else
{
characterAnimator.SetBool("IsRide", false);
}
}
//计算功率 速度 当前骑行总里程M心率 踏频 等
protected virtual void Compute()
{
//power = 900;//功率
//speed = Helper.CalculateSpeed(elevation, 0, power, 65, 7);
//distance = Math.Round(speed / 3600, 6);
//totalDistance += distance;
}
//当前用户调用来上传骑行记录
protected virtual void Upload()
{
}
#endregion
#region
public int CurrentIndex;
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
void ComputeNextSlope()
{
double sumDistance = 0;
var pointList = mapData.List;
int index = 0;
for (int i = 0; i < pointList.Count; i++)
{
sumDistance += pointList[i].Distance;
if (totalDistance * 1000 <= sumDistance)
{
index = i;
break;
}
}
//计算当前海拔和坡度
elevation = pointList[index].Elevation;
currentSlope = pointList[index].Grade;
//计算下一个点的坡度和距离
int nextIndex = index == pointList.Count - 1 ? index : index + 1;
CurrentIndex = nextIndex;
nextSlope = pointList[nextIndex].Grade;
nextSlopeDistance = sumDistance - totalDistance * 1000;
currentSlopeDistance = totalDistance * 1000 - (sumDistance - pointList[index].Distance);
}
//根据距离计算坐标
Vector2d Along(double endDistance)
{
if (mapData != null)
{
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);
}
return nextlatlong;
}
#endregion
#region
IEnumerator LookAtNextPos()
{
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
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;
}
}
//人物移动控制
IEnumerator MoveTo()
{
//让人物移动分点增加动画的流畅度
float t = 0;
while (t < 1)
{
t += Time.deltaTime;
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
transform.localPosition = v;
//控制海拔图的位置
yield return null;
}
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f01d57cfa983552409f7c9e896892c31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -193,7 +193,7 @@ public class CyclingController : MonoBehaviour
if (result != null && result.List.Count > 0)
{
mapData = result;
coordiantes = result.List[0].Point;
coordiantes = result.List[0].Point;//TODO计算当前用户所处的位置
initComplete = true;
}
else

View File

@ -1,184 +1,21 @@
using System.Collections;
using UnityEngine;
using Mapbox.Unity.Map;
using Mapbox.Utils;
using Assets.Scripts.Apis.Models;
using static Assets.Scripts.Apis.Models.MapDataModel;
using System;
using Random = UnityEngine.Random;
using Assets.Scripts.Apis;
using GeoJSON.Net.Geometry;
using TurfCS;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System;
namespace Assets.Scenes.Ride.Scripts
{
public class OtherPlayerController : MonoBehaviour
public class OtherPlayerController : AbstractPlayer
{
[Header("Character")]
[SerializeField]
GameObject character;
[SerializeField]
Animator characterAnimator;
protected override void Init()
{
base.Init();
SetStart();//自动开始
}
AbstractMap map;
#region
Vector3 nextPos;
Vector3 prePos;
Vector2d currentlatlong; //当前坐标
Vector2d nextlatlong; //下一个点的坐标
float timer = 1.0f;//计时器
#endregion
#region
bool isStart;
bool isMajor;//是否是主人公
MapDataModel mapData;
int userId;
DateTime startTime;//开始骑行时间
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
void Start()
{
characterAnimator = GetComponentInChildren<Animator>();
var mainController = transform.parent.GetComponent<CyclingController>();
map = FindObjectOfType<AbstractMap>();
mapData = mainController.GetMapData();//获取路书信息
isStart = true;
}
void Update()
{
timer -= Time.deltaTime;
if (timer <= 0)//定时器 一秒执行一次
{
Run();
timer = 1.0f;
}
}
#region
//骑行中
void Run()
{
if (IsStart)
{
power = 900;//功率
speed = Helper.CalculateSpeed(elevation, 0, power, 65, 7);
distance = Math.Round(speed / 3600, 6);
totalDistance += distance;
characterAnimator.SetBool("IsRide", false);//初始化动画状态
if (totalDistance <= mapData.TotalDistance)
{
//数据处理
ticks++;
nextlatlong = Along(totalDistance);//下一个坐标
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
nextPos.y += 0.3f;
prePos = transform.localPosition;//当前点
//动画控制
if (distance > 0)
{
characterAnimator.SetBool("IsRide", true);//开始移动动画
StartCoroutine(LookAtNextPos());//转向
StartCoroutine(MoveTo());//移动
}
}
else
{
//TODO保存骑行数据
characterAnimator.SetBool("ReachEnd", true);
}
}
else
{
characterAnimator.SetBool("IsRide", false);
}
}
#endregion
#region
public int CurrentIndex;
//根据距离计算坐标
Vector2d Along(double endDistance)
{
if (mapData != null)
{
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);
}
return nextlatlong;
}
#endregion
#region
IEnumerator LookAtNextPos()
{
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
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;
}
}
//人物移动控制
IEnumerator MoveTo()
{
//让人物移动分点增加动画的流畅度
float t = 0;
while (t < 1)
{
t += Time.deltaTime;
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
transform.localPosition = v;
//控制海拔图的位置
yield return null;
}
}
#endregion
}
protected override void Compute()
{
power = 900;//功率
speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight);
distance = Math.Round(speed / 3600, 6);
totalDistance += distance;
}
}
}

View File

@ -1,225 +1,57 @@
using System.Collections;
using UnityEngine;
using Mapbox.Unity.Map;
using Mapbox.Utils;
using UnityEngine;
using Assets.Scripts.Apis.Models;
using static Assets.Scripts.Apis.Models.MapDataModel;
using System;
using Random = UnityEngine.Random;
using Assets.Scripts.Apis;
using GeoJSON.Net.Geometry;
using TurfCS;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using Assets.Scenes.Ride.Scripts.Model;
using static CyclingController;
using System.IO;
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
using System.Threading.Tasks;
namespace Assets.Scenes.Ride.Scripts
{
public class PlayerController : MonoBehaviour
public class PlayerController : AbstractPlayer
{
[Header("Character")]
[SerializeField]
GameObject character;
[SerializeField]
Animator characterAnimator;
//[SerializeField]
AbstractMap map;
#region
Vector3 nextPos;
Vector3 prePos;
Vector2d currentlatlong; //当前坐标
Vector2d nextlatlong; //下一个点的坐标
float timer = 1.0f;//计时器
#endregion
#region
bool isStart;
bool isMajor;//是否是主人公
MapDataModel mapData;
int userId;
int routeId;
DateTime startTime;//开始骑行时间
BaseCycling baseCycling;
double speed;
double power;
double elevation;
double cadance;
int heartRate;
int ticks;
double totalDistance;
double currentSlope;
double nextSlope;
double nextSlopeDistance;
double currentSlopeDistance;
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 Distance { get => distance; }
public double CurrentSlope { get => currentSlope; }
public double NextSlope { get => nextSlope;}
public double NextSlopeDistance { get => nextSlopeDistance; }
public double CurrentSlopeDistance { get => currentSlopeDistance; }
public double Elevation { get => elevation; }
#endregion
void Start()
{
characterAnimator = GetComponentInChildren<Animator>();
var mainController = transform.parent.GetComponent<CyclingController>();
map = FindObjectOfType<AbstractMap>();
mapData = mainController.GetMapData();//获取路书信息
routeId = mainController.RouteId;//路数id
Initialize(mainController.GetCenterCoordinate());//初始人物
baseCycling = mainController.cyclingController;
}
void Update()
{
timer -= Time.deltaTime;
if (timer <= 0)//定时器 一秒执行一次
{
Run();
timer = 1.0f;
}
}
#region
//开始骑行
public void SetStart()
{
isStart = true;
startTime = DateTime.Now;
}
//继续骑行
public void SetContinue()
{
isStart = true;
}
//暂停骑行
public void SetPause()
{
isStart = false;
Complete();
}
#endregion
#region
//初始化玩家距离/朝向
void Initialize(double[] coordinates)
{
ticks = 0;//当前骑行时间
//初始化人物位置
totalDistance = 0;//TODO:根据骑行模式动态取值 KM
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);
}
public List<TargetData> RiderDatas = new List<TargetData>();
//骑行中
void Run()
{
ComputeMapData();//计算海拔&坡度&下一个点信息
if (IsStart)
{
//CamControl();
power = 2000;//功率
speed = Helper.CalculateSpeed(elevation, currentSlope, power, 65, 7);
distance = Math.Round(speed / 3600, 6);
totalDistance += distance;
protected override void Init()
{
base.Init();
characterAnimator.SetBool("IsRide", false);//初始化动画状态
if (totalDistance <= mapData.TotalDistance)
{
//数据处理
ticks++;
nextlatlong = Along(totalDistance);//下一个坐标
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
nextPos.y += 0.3f;
prePos = transform.localPosition;//当前点
//记录骑行数据
var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
Debug.Log(recordText);
RiderDatas.Add(new TargetData
{
Ticks = ticks,
_Power = power,
_Speed = speed,
_Distance = totalDistance,
_Cadence = cadance,
_HeartRate = heartRate,
_Lat = nextlatlong.x,
_Lon = nextlatlong.y
});
//动画控制
if (distance > 0)
{
characterAnimator.SetBool("IsRide", true);//开始移动动画
StartCoroutine(LookAtNextPos());//转向
StartCoroutine(MoveTo());//移动
}
}
else
{
totalDistance = mapData.TotalDistance;
characterAnimator.SetBool("ReachEnd", true);
////记录骑行数据
//var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
//Debug.Log(recordText);
//RiderDatas.Add(new TargetData
//{
// Ticks = ticks,
// _Power = power,
// _Speed = speed,
// _Distance = totalDistance,
// _Cadence = cadance,
// _HeartRate = heartRate,
// _Lat = nextlatlong.x,
// _Lon = nextlatlong.y
//});
Task.Run(() =>
{
Complete();
});
isStart = false;
}
}
else
{
characterAnimator.SetBool("IsRide", false);
}
}
//发送当前用户位置给UDPs
void SendUdp() {
}
//TODO骑行结束
private int weight = 65;
private int bicycleWeight = 7;
protected override void Compute()
{
//计算数据
power = 2000;//功率
speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight);
distance = Math.Round(speed / 3600, 6);
totalDistance += distance;
//记录骑行数据
var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
Debug.Log(recordText);
RiderDatas.Add(new TargetData
{
Ticks = ticks,
_Power = power,
_Speed = speed,
_Distance = totalDistance,
_Cadence = cadance,
_HeartRate = heartRate,
_Lat = nextlatlong.x,
_Lon = nextlatlong.y
});
}
//上传数据
protected override void Upload()
{
}
#region
private string ContinueMark = "TODO";
private int ContinueIndex=0;
private int Competitionid =0;
@ -245,7 +77,7 @@ namespace Assets.Scenes.Ride.Scripts
var interruptRecord = new MapInterruptRecord
{
Id = recordId,
RouteId = routeId,
RouteId = 1,
RouteName = "",
TotalDistance = mapData.TotalDistance,
UserId = userId,
@ -310,107 +142,8 @@ namespace Assets.Scenes.Ride.Scripts
var result = api.Add(interruptRecord, files);
}
#endregion
#region
public int CurrentIndex;
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
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 * 1000 <= sumDistance)
{
index = i;
break;
}
}
//计算当前海拔和坡度
elevation = pointList[index].Elevation;
currentSlope = pointList[index].Grade;
//计算下一个点的坡度和距离
int nextIndex = index == pointList.Count - 1 ? index : index + 1;
CurrentIndex = nextIndex;
nextSlope = pointList[nextIndex].Grade;
nextSlopeDistance = sumDistance - totalDistance*1000;
currentSlopeDistance = totalDistance * 1000 - (sumDistance- pointList[index].Distance);
}
//根据距离计算坐标
Vector2d Along(double endDistance)
{
if (mapData != null)
{
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);
}
return nextlatlong;
}
#endregion
#region
IEnumerator LookAtNextPos()
{
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
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;
}
}
//人物移动控制
IEnumerator MoveTo()
{
//让人物移动分点增加动画的流畅度
float t = 0;
while (t < 1)
{
t += Time.deltaTime;
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
transform.localPosition = v;
//控制海拔图的位置
yield return null;
}
}
#endregion
#region
//[Header("CameraSettings")]
//[SerializeField]
//Camera cam;
//Vector3 previousPos = Vector3.zero;
//Vector3 deltaPos = Vector3.zero;
// IEnumerator CamControl()//替换成cinemachine
//{
// if (cam != null)
// {
// 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;
// }
// }
//}
#endregion
}
#endregion
}
}