// 离开状态 public void OnLeave() { MoveSyncFlag sendSync = MoveSyncFlag.TO_SERVER; int curTick = System.Environment.TickCount; if (m_pFSM) { m_pFSM.syncTick = curTick; Vector3 sendVelocity = Vector3.zero; m_pFSM.syncVelocity = sendVelocity; m_pFSM.syncPosition = m_pFSM.transform.position; m_pFSM.syncAngle = m_pFSM.transform.eulerAngles; } Send_Sync_Position(sendSync); bWallWalking = false; m_wallWalkingState = WallWalkingState.none; if (m_pFSM) { m_pFSM.animator.SetBool(hashid_isWallWalking, false); m_pFSM.animator.SetBool(hashid_isUpWall, false); m_pFSM.animator.SetBool(hashid_isDownWall, false); m_pFSM.enableCollider(true); } }
public void Send_Sync_Position(MoveSyncFlag reportToSever) { // trace if (m_pFSM == null) { Trace.LogError("CreatureState_Jomp.cs Send_Sync_Position m_pFSM == null"); return; } //如果上报位置范围不对,则输出至LOG,退出 if (float.IsNaN(tr.position.x) || float.IsNaN(tr.position.y) || float.IsNaN(tr.position.z) || Math.Abs(tr.position.x) > SceneManager.MAX_SCENE_SIZE || Math.Abs(tr.position.y) > SceneManager.MAX_SCENE_SIZE || Math.Abs(tr.position.z) > SceneManager.MAX_SCENE_SIZE) { Debug.LogError(m_pFSM.name + " Jumping Send_Sync_Position Position Error " + tr.position); return; } cmd_creature_rigidbody_sync data = new cmd_creature_rigidbody_sync(); data.nCreatureState = (int)EntityState.Glide; data.fPosition_x = tr.position.x; data.fPosition_y = tr.position.y; data.fPosition_z = tr.position.z; // 直接用欧拉角 data.fRotation_x = tr.rotation.eulerAngles.x; data.fRotation_y = tr.rotation.eulerAngles.y; data.fRotation_z = tr.rotation.eulerAngles.z; data.fVelocity_x = m_pFSM.syncVelocity.x; data.fVelocity_y = m_pFSM.syncVelocity.y; data.fVelocity_z = m_pFSM.syncVelocity.z; data.nSyn2Server = (int)reportToSever; EntityEventHelper.Instance.SendCommand <cmd_creature_rigidbody_sync>(m_pFSM.entityID, EntityLogicDef.ENTITY_CMD_SET_POS, ref data); // 通知主角位置发生变化 U3D_Render.EntityLocUpdate.SendActorLocationChange(new Vector3(tr.position.x, tr.position.y, tr.position.z)); EntityBatchCommunicator.SendEntityPro(m_pFSM.entityID, tr.position, tr.rotation.eulerAngles); }
private void updateStep() { if (m_wallWalkSpeed < 0.01f) { stopWallWalk(); return; } Vector3 walkStep = m_wallWalkTargetPos - m_pFSM.transform.position; float stepLength = m_wallWalkSpeed * Time.deltaTime; if (walkStep.magnitude <= stepLength) { //m_pFSM.controller.Move(walkStep); m_pFSM.transform.position += walkStep; nextStep(); } else { walkStep.Normalize(); walkStep = walkStep * stepLength; //m_pFSM.controller.Move(walkStep); m_pFSM.transform.position += walkStep; } int curTick = System.Environment.TickCount; if (curTick - m_lastSyncTick > 200) { m_lastSyncTick = curTick; MoveSyncFlag sendSync = MoveSyncFlag.TO_SERVER; m_pFSM.syncTick = curTick; Vector3 sendVelocity = walkStep.normalized * m_wallWalkSpeed; m_pFSM.syncVelocity = sendVelocity; m_pFSM.syncPosition = m_pFSM.transform.position; m_pFSM.syncAngle = m_pFSM.transform.eulerAngles; Send_Sync_Position(sendSync); } }
/////////////////////////////////////////////////////////////////////////////////////////////////////////// // 发送一次位置同步 public void Send_Sync_Position(MoveSyncFlag reportToSever) { if (m_pFSM == null) { Trace.LogError("CreatureState_Standing.cs Send_Sync_Position m_pFSM == null"); return; } //如果上报位置范围不对,则输出至LOG,退出 if (float.IsNaN(m_pFSM.syncPosition.x) || float.IsNaN(m_pFSM.syncPosition.y) || float.IsNaN(m_pFSM.syncPosition.z) || Math.Abs(m_pFSM.syncPosition.x) > SceneManager.MAX_SCENE_SIZE || Math.Abs(m_pFSM.syncPosition.y) > SceneManager.MAX_SCENE_SIZE || Math.Abs(m_pFSM.syncPosition.z) > SceneManager.MAX_SCENE_SIZE) { Debug.LogError(m_pFSM.name + " standing Send_Sync_Position Position Error " + m_pFSM.syncPosition); return; } cmd_creature_rigidbody_sync data = new cmd_creature_rigidbody_sync(); data.nCreatureState = (int)EntityState.WallWalking; data.fPosition_x = m_pFSM.syncPosition.x; data.fPosition_y = m_pFSM.syncPosition.y; data.fPosition_z = m_pFSM.syncPosition.z; // 直接用欧拉角 data.fRotation_x = m_pFSM.syncAngle.x; data.fRotation_y = m_pFSM.syncAngle.y; data.fRotation_z = m_pFSM.syncAngle.z; data.fVelocity_x = m_pFSM.syncVelocity.x; data.fVelocity_y = m_pFSM.syncVelocity.y; data.fVelocity_z = m_pFSM.syncVelocity.z; data.nSyn2Server = (int)reportToSever; EntityEventHelper.Instance.SendCommand <cmd_creature_rigidbody_sync>(m_pFSM.entityID, EntityLogicDef.ENTITY_CMD_SET_POS, ref data); if (tr == null) { Trace.LogError("CreatureState_Standing.cs Send_Sync_Position tr == null"); return; } if (tr.position == null) { Trace.LogError("CreatureState_WallWalking.cs Send_Sync_Position tr.SetPosition== null"); return; } if (tr.rotation == null) { Trace.LogError("CreatureState_WallWalking.cs Send_Sync_Position tr.rotation == null"); return; } if (tr.rotation.eulerAngles == null) { Trace.LogError("CreatureState_WallWalking.cs Send_Sync_Position tr.rotation.eulerAngles == null"); return; } EntityBatchCommunicator.SendEntityPro(m_pFSM.entityID, tr.position, tr.rotation.eulerAngles); if (m_pFSM.isHero) { U3D_Render.EntityView ev = EntityFactory.getPlayerViewByID(m_pFSM.entityID); MapFinderManager.MoveObject(ref ev, tr.position); } }
private void UpdateFunction() { if (floatingState == FloatingState.Down && grounded) { m_pFSM.ChangeState((int)EntityState.Standing, IntPtr.Zero); //float landingSpeed = m_lastvelocity.y; //float maxFallSpeed = m_pFSM.SkinConfig == null ? -30 : -m_pFSM.SkinConfig.maxFallSpeed * 2.0f; float fallHeight = startHeight - m_pFSM.transform.position.y; //if (landingSpeed > maxFallSpeed / 2.0f) //着陆大于最大速度的一半,可能需要计算伤害,上报逻辑层 if (m_pFSM.isHero && fallHeight > 5.0f) //着陆时落差大于5米,则上报逻辑层 { cmd_creature_act_landspeed data = new cmd_creature_act_landspeed(); data.fValue = fallHeight; IntPtrHelper helper = new IntPtrHelper(); int len = Marshal.SizeOf(data); IntPtr ptr = helper.toPtr <cmd_creature_act_landspeed>(ref data); int eventID = (int)EntityLogicDef.ENTITY_CMD_LANDING_SPEED; GameLogicAPI.onEntityEvent(m_pFSM.entityID, eventID, len, "", ptr, len); if (m_pFSM.showLog) { Trace.Log("Big Landing! fallHeight=" + fallHeight.ToString()); } } } uint currentTick = GameLogicAPI.getTickCount(); int deltaTick = (int)(currentTick - lastFrameTick); deltaTick = deltaTick < 1 ? 1 : deltaTick; lastFrameTick = currentTick; deltaTime = ((float)deltaTick) / 1000.0f; if (m_lastFrameDeltaTime <= 0.01f) { m_lastFrameDeltaTime = deltaTime; } if (m_pFSM.moveCtrl.isCharge()) { //Trace.LogWarning("can't move: m_pFSM.bForceMoving=" + m_pFSM.bForceMoving.ToString() + ",m_pFSM.bForceFlighting=" + m_pFSM.bForceFlighting.ToString()); return; } sendSync = MoveSyncFlag.NOT_2_SERVER; //-------------------------------------------------------- // 下面算速度 //-------------------------------------------------------- //float finalInertiaAcceleration = m_accSpeed; //惯性加速度 currentvelocity = new Vector3(0.0f, 0.0f, 0.0f); bool forceUp = false; if (m_pFSM.isHero && !m_pFSM.bControlledBySever) //主角的话下面多折腾下速度 { // Calculate the velocity based on the current and previous position. // This means our velocity will only be the amount the character actually moved as a result of collisions. //Vector3 oldHVelocity = new Vector3(lastvelocity.x, 0, lastvelocity.z); //Vector3 newHVelocity = lastoffset / deltaTime; //newHVelocity = new Vector3(newHVelocity.x, 0, newHVelocity.z); //// The CharacterController can be moved in unwanted directions when colliding with things. //// We want to prevent this from influencing the recorded velocity. //if (oldHVelocity == Vector3.zero) //{ // newHVelocity = new Vector3(0, newHVelocity.y, 0); //} //else //{ // float projectedNewVelocity = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude; // newHVelocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + newHVelocity.y * Vector3.up; //} //if (newHVelocity.y < currentvelocity.y - 0.001) //{ // if (newHVelocity.y < 0) // { // // Something is forcing the CharacterController down faster than it should. // // Ignore this // newHVelocity.y = lastvelocity.y; // } //} // Update velocity based on input //newHVelocity = ApplyInputVelocityChange(newHVelocity); Vector3 newHVelocity = ApplyInputVelocityChange(m_lastvelocity); //if (newHVelocity.sqrMagnitude < 0.001f) //如果是停止的,就不计算惯性速度,免得技能僵直之类的效果生效不够及时 //{ // currentvelocity = newHVelocity; //} //else //{ currentvelocity = newHVelocity; //} //这里记录的是没经过ApplyYSpeed的Y轴调整的速度 m_lastvelocity = currentvelocity; // 判断本地的模拟坐标和真实坐标的差别, 只有达到一定阀值才需要同步 // 暂时在行走过程中200ms同步一次 int curTick = System.Environment.TickCount; if (currentvelocity.sqrMagnitude <= 0.001f) { currentvelocity = Vector3.zero; } // 启动和站立强制同步一次 if ((m_pFSM.syncVelocity.sqrMagnitude > 0.001f && currentvelocity.sqrMagnitude <= 0.001f) || (m_pFSM.syncVelocity.sqrMagnitude <= 0.001f && currentvelocity.sqrMagnitude > 0.001f)) { sendSync = MoveSyncFlag.TO_BROADCAST; } // 每200毫秒根据速度或者移动距离考虑是否同步一次 else if (curTick >= m_pFSM.syncTick + m_pFSM.syncInterval) { //速度/位置/旋转分别跟上一次同步的数据比对看是否需要同步 Vector3 velSub = currentvelocity - m_pFSM.syncVelocity; Vector3 posSub = tr.position - m_pFSM.syncPosition; Vector3 rotSub = tr.eulerAngles - m_pFSM.syncAngle; if (velSub.sqrMagnitude > 0.01f || posSub.sqrMagnitude > 0.01f || rotSub.sqrMagnitude > 0.01f) { sendSync = MoveSyncFlag.TO_SERVER; } } if (floatingState == FloatingState.Down && curTick >= m_pFSM.syncTick + m_pFSM.syncInterval / 4) { sendSync = MoveSyncFlag.TO_SERVER; } currentvelocity = ApplyYSpeed(currentvelocity, ref forceUp); } else//不是主角直接用同步的速度 { currentvelocity = m_pFSM.syncVelocity; Vector3 deltapos = m_pFSM.syncPosition - tr.position; float dis = deltapos.magnitude; if (m_pFSM.syncVelocity.sqrMagnitude < 0.001f && dis > 0.01f) //速度为0,但还没到同步的目的地,补偿一下误差 { float alpha = Mathf.Clamp01((dis - 0.01f) / approximatethre); //对速度根据离同步位置误差距离作逼近收敛修正 float speed = (1.0f - alpha) * 0.0f + alpha * approximatethre * apmtspeedratio; currentvelocity = deltapos.normalized * speed; } else { //Vector3 newHVelocity = m_pFSM.syncVelocity; //Vector3 oldHVelocity = new Vector3(lastvelocity.x, 0, lastvelocity.z); //Vector3 HVelocityDelta = newHVelocity - oldHVelocity; //float advance = deltaTime * finalInertiaAcceleration; //if (advance > HVelocityDelta.magnitude) advance = HVelocityDelta.magnitude; //currentvelocity = oldHVelocity + HVelocityDelta.normalized * advance; currentvelocity = m_pFSM.syncVelocity; } currentvelocity = ApplyYSpeed(currentvelocity, ref forceUp); } //-------------------------------------------------------- // 下面算位置 //-------------------------------------------------------- // We always want the movement to be framerate independent. Multiplying by Time.deltaTime does this. if (deltaTime > m_lastFrameDeltaTime * 2.0f || deltaTime < m_lastFrameDeltaTime / 2.0f) //缓冲帧率突变产生的跳跃 { deltaTime = deltaTime * m_pFSM.frameAccFactor + m_lastFrameDeltaTime * (1 - m_pFSM.frameAccFactor); } m_lastFrameDeltaTime = deltaTime; Vector3 currentOffset = currentvelocity * deltaTime; m_pFSM.syncDetalTime += deltaTime; // Find out how much we need to push towards the ground to avoid loosing grouning // when walking down a step or over a sharp change in slope. if (m_pFSM.isHero && !m_pFSM.bControlledBySever)//主角 { if (m_pFSM.ShiftEnable) { //if (InputManager.GetKey(KeyCode.LeftShift) || InputManager.GetKey(KeyCode.RightShift))//主角暂时添加加速快捷键以便测试 { currentOffset *= 5.0f; } } } else //非主角 { //Vector3 idealPos = tr.position; //calSyncOffset(currentvelocity, ref currentOffset, ref idealPos); if (/*floatingState != FloatingState.Down &&*/ !forceUp) //下落的时候采用同步位置会上下拉扯,没到规定高度的时候不等同步包强制上升 { if (floatingState == FloatingState.Down) { // 下落过程中不用同步位置会在这段不同步 所以还是要使用水平方向的同步位置 // 下落时垂直速度要向下 不能因为同步位置还没过来掉一段再往上个同步位置拉 Vector3 dirHrz = m_pFSM.syncPosition - tr.position; dirHrz.y = 0; Vector3 dirNormal = dirHrz.normalized; dirNormal.y = -1; dirNormal = dirNormal.normalized; currentvelocity = dirNormal * currentvelocity.magnitude; } else { Vector3 dir = (m_pFSM.syncPosition - tr.position).normalized; currentvelocity = dir * currentvelocity.magnitude; } } currentOffset = currentvelocity * deltaTime; if (currentOffset.sqrMagnitude < 0.001f) { currentvelocity = Vector3.zero; } } //-------------------------------------------------------- // 下面更新animator //-------------------------------------------------------- if (m_pFSM.animator != null) { if (!m_pFSM.isHero || m_pFSM.bControlledBySever) { //m_lastvelocity是特殊处理飞行时候的移动速度,是它播放合适的动作 currentvelocity = m_lastvelocity; } Vector3 planeVel = new Vector3(currentvelocity.x, 0, currentvelocity.z); if (planeVel.sqrMagnitude > 0.001f) { m_pFSM.animator.SetBool("isMoving", true); //m_pFSM.animatorCtrl.ana.SetBool("isMoving", true); bIsMoving = true; } else { m_pFSM.animator.SetBool("isMoving", false); //m_pFSM.animatorCtrl.ana.SetBool("isMoving", false); bIsMoving = false; } //取移动速度相对于主角面向的向前和向左的标量 Vector3 projectVel = Vector3.zero; projectVel.x = Vector3.Dot(m_lastvelocity, tr.right); //m_lastvelocity是排除Y方向操作速度的原始速度,可以用来计算方向动作 projectVel.z = Vector3.Dot(m_lastvelocity, tr.forward); float fRight = 0.0f; float fForward = 0.0f; if (projectVel.sqrMagnitude > 0.0036f)//同步过来的速度为0之后,点乘还会有误差,造成轻微移动动作 { fForward = projectVel.z / m_maxSpeed; fRight = projectVel.x / m_maxSpeed; } if (Mathf.Abs(fRight) < 0.06f) { fRight = 0.0f; } if (Mathf.Abs(fForward) < 0.06f) { fForward = 0.0f; } fForward = Mathf.Min(fForward, 1.0f); fForward = Mathf.Max(fForward, -1.0f); fRight = Mathf.Min(fRight, 1.0f); fRight = Mathf.Max(fRight, -1.0f); //移动速度考虑了服务器速度和基本速度的比率后,按服务器速度算animator参数值 //fForward = fForward / m_maxSpeed; //fRight = fRight / m_maxSpeed; m_pFSM.animator.SetFloat("moveright", fRight); m_pFSM.animator.SetFloat("moveforward", fForward); m_pFSM.animator.SetFloat("velocity", currentvelocity.magnitude); if (wingAnimator) { wingAnimator.SetFloat("moveright", fRight); wingAnimator.SetFloat("moveforward", fForward); } if (m_pFSM.animatorCtrl.anb != null) { m_pFSM.animatorCtrl.anb.SetFloat("moveright", fRight); m_pFSM.animatorCtrl.anb.SetFloat("moveforward", fForward); } } //-------------------------------------------------------- // 下面更新transform //-------------------------------------------------------- // Save lastPosition for velocity calculation. Vector3 oldPosition = tr.position; float curtime = Time.time; if (m_pFSM.isHero && !m_pFSM.bControlledBySever)//是主角,都用耗时的物理行走方法 { m_pFSM.collisionFlags = m_pFSM.controller.Move(currentOffset); ++heroMoveTimes; } else//非主角 { float pos_dis = (m_pFSM.syncPosition - tr.transform.position).magnitude; if (m_pFSM.syncVelocity.sqrMagnitude < 0.01f && m_pFSM.animatorCtrl.bDoingAttackMove) { pos_dis = 0.0f; //正在利用动作控制位移,就不按同步包移动了 } if ((floatingState == FloatingState.Down) || (physenable && pos_dis > approximatethre) || (forceUp)) //上下落或者跟同步位置差距较大时用耗时的物理行走方法 { m_pFSM.collisionFlags = m_pFSM.controller.Move(currentOffset); } else if (pos_dis > 0.01f) //否则用较小耗时的渐趋逼近公式 { Vector3 deltapos = m_pFSM.syncPosition - tr.transform.position; Vector3 curPos; if (deltapos.sqrMagnitude > currentOffset.sqrMagnitude) { curPos = tr.transform.position + currentOffset; } else { curPos = tr.transform.position * 0.5f + m_pFSM.syncPosition * 0.5f; } tr.transform.SetPosition(curPos); } //特殊处理飞行时候的移动速度,是它播放合适的动作 Vector3 deltaDis = m_pFSM.syncPosition - tr.transform.position; Vector3 newVectory = Vector3.zero; if (deltaDis.sqrMagnitude > 0.01f) { newVectory = currentOffset; newVectory.y = 0; newVectory = newVectory.normalized * m_maxSpeed; } m_lastvelocity = m_lastvelocity * 0.3f + newVectory * 0.7f; } if (m_pFSM.isHero && !m_pFSM.bControlledBySever)//主角不用平滑角度 { } else//非主角才平滑角度角度 { float angle_dis = (m_pFSM.syncAngle - tr.transform.eulerAngles).magnitude; if (angle_dis > 0.1f) //角度差距较大时采用逼近公式 { Vector3 newangle; newangle.x = Mathf.LerpAngle(tr.eulerAngles.x, m_pFSM.syncAngle.x, 0.2f); newangle.y = Mathf.LerpAngle(tr.eulerAngles.y, m_pFSM.syncAngle.y, 0.2f); newangle.z = Mathf.LerpAngle(tr.eulerAngles.z, m_pFSM.syncAngle.z, 0.2f); tr.eulerAngles = newangle; } } lastupdatetime = curtime; lastoffset = currentOffset; //最后算完才上报 if (sendSync != MoveSyncFlag.NOT_2_SERVER && (m_pFSM.isHero && !m_pFSM.bControlledBySever)) { int curTick = System.Environment.TickCount; m_pFSM.syncTick = curTick; Vector3 sendVelocity = currentvelocity; m_pFSM.syncVelocity = sendVelocity; m_pFSM.syncPosition = tr.position; m_pFSM.syncAngle = tr.eulerAngles; Send_Sync_Position(sendSync); } else if (heroMoveTimes >= 8) { Vector3 sendVelocity = new Vector3(currentvelocity.x, 0.0f, currentvelocity.z); updatePosWithoutSend(sendVelocity, tr.position, tr.eulerAngles); heroMoveTimes = 0; } //移动完更新地面判断 grounded = m_pFSM.groundNormal.y > 0.01f; }
public void Send_Sync_Position(MoveSyncFlag reportToSever) { }
private void UpdateFunction() { deltaTime = Time.deltaTime; if (deltaTime < 0.001f) { #if UNITY_EDITOR Debug.LogError("deltaTime=" + deltaTime); #else Trace.Log("deltaTime=" + deltaTime); #endif return; } if (m_lastFrameDeltaTime <= 0.01f) { m_lastFrameDeltaTime = deltaTime; } if (m_pFSM.moveCtrl.isCharge()) { if (m_pFSM.animator != null) { //Trace.LogWarning("can't move: m_pFSM.bForceMoving=" + m_pFSM.bForceMoving.ToString() + ",m_pFSM.bForceFlighting=" + m_pFSM.bForceFlighting.ToString()); m_pFSM.animator.SetFloat(hashid_moveforward, 0); m_pFSM.animator.SetFloat(hashid_moveright, 0); m_pFSM.animator.SetFloat(hashid_velocity, 0); m_pFSM.animator.SetBool(hashid_isMoving, false); } return; } sendSync = MoveSyncFlag.NOT_2_SERVER; //-------------------------------------------------------- // 下面算速度 //-------------------------------------------------------- if (float.IsNaN(m_pFSM.creaturePropety.runSpeed_Forward)) { Debug.LogError(m_pFSM.name + " Standing m_pFSM.creaturePropety.runSpeed_Forward error:" + m_pFSM.creaturePropety.runSpeed_Forward); return; } float finalInertiaAcceleration = m_pFSM.creaturePropety.InertiaAcceleration * ((m_pFSM.maxForwardSpeed / m_pFSM.creaturePropety.runSpeed_Forward - 1.0f) * m_pFSM.creaturePropety.InertiaScale + 1.0f); //惯性加速度 currentvelocity = new Vector3(0.0f, 0.0f, 0.0f); if (m_pFSM.isHero && !m_pFSM.bControlledBySever) //主角的话下面多折腾下速度 { // Calculate the velocity based on the current and previous position. // This means our velocity will only be the amount the character actually moved as a result of collisions. Vector3 oldHVelocity = new Vector3(lastvelocity.x, 0, lastvelocity.z); Vector3 newHVelocity = lastoffset / deltaTime; newHVelocity = new Vector3(newHVelocity.x, 0, newHVelocity.z); // The CharacterController can be moved in unwanted directions when colliding with things. // We want to prevent this from influencing the recorded velocity. //if (oldHVelocity == Vector3.zero) if (oldHVelocity.sqrMagnitude < 0.0001f) { newHVelocity = new Vector3(0, newHVelocity.y, 0); } else { float projectedNewVelocity = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude; //方向不变 夹角为0 点积为|a||b|*1 newHVelocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + newHVelocity.y * Vector3.up; } if (newHVelocity.y < currentvelocity.y - 0.001f) { if (newHVelocity.y < 0) { // Something is forcing the CharacterController down faster than it should. // Ignore this newHVelocity.y = lastvelocity.y; } } // Update velocity based on input newHVelocity = ApplyInputVelocityChange(newHVelocity); if (newHVelocity.sqrMagnitude < 0.0001f) //如果是停止的,就不计算惯性速度,免得技能僵直之类的效果生效不够及时 { if (InputMoveDirectionDelay > 0.2f) { currentvelocity = newHVelocity; } else { //短暂的停止按键留有缓冲时间 currentvelocity = oldHVelocity; InputMoveDirectionDelay += deltaTime; } } else { if (InputMoveDirectionDelay != 0) { InputMoveDirectionDelay = 0; } Vector3 HVelocityDelta = newHVelocity - oldHVelocity; float advance = deltaTime * finalInertiaAcceleration; if (advance > HVelocityDelta.magnitude) { advance = HVelocityDelta.magnitude; } currentvelocity = oldHVelocity + HVelocityDelta.normalized * advance; if (currentvelocity.magnitude <= 0.1f) { //按键输入不为0,速度过度时减速最低不能为0,防止上发判断为停止 currentvelocity = currentvelocity.normalized * 0.5f; } } // 判断本地的模拟坐标和真实坐标的差别, 只有达到一定阀值才需要同步 // 暂时在行走过程中200ms同步一次 int curTick = System.Environment.TickCount; //if (currentvelocity.sqrMagnitude <= 0.0001f && currentvelocity != Vector3.zero) //{ // currentvelocity = Vector3.zero; //} //if (currentvelocity == Vector3.zero) //{ // m_pFSM.RunSpeedUpUpdateInfo(0, 0); //} // 启动和站立强制同步一次 if ((m_pFSM.syncVelocity.sqrMagnitude > 0.0001f && currentvelocity.sqrMagnitude <= 0.0001f) || (m_pFSM.syncVelocity.sqrMagnitude <= 0.0001f && currentvelocity.sqrMagnitude > 0.001f)) { sendSync = MoveSyncFlag.TO_BROADCAST; } // 每syncInterval毫秒根据速度或者移动距离考虑是否同步一次 else if (curTick >= m_pFSM.syncTick + m_pFSM.syncInterval) { //速度/位置/旋转分别跟上一次同步的数据比对看是否需要同步 Vector3 velSub = currentvelocity - m_pFSM.syncVelocity; Vector3 posSub = tr.position - m_pFSM.syncPosition; Vector3 rotSub = tr.eulerAngles - m_pFSM.syncAngle; if (velSub.sqrMagnitude > 0.01f || posSub.sqrMagnitude > 0.01f || rotSub.sqrMagnitude > 0.01f) { sendSync = MoveSyncFlag.TO_SERVER; } } currentvelocity = ApplyGravity(currentvelocity); //主角的话添加重力到速度 } else//不是主角直接用同步的速度 { currentvelocity = m_pFSM.syncVelocity; Vector3 deltapos = m_pFSM.syncPosition - tr.position; float dis = deltapos.magnitude; if (m_pFSM.syncVelocity.sqrMagnitude < 0.001f && dis > 0.01f) //速度为0,但还没到同步的目的地,补偿一下误差 { float alpha = Mathf.Clamp01((dis - 0.01f) / approximatethre); //对速度根据离同步位置误差距离作逼近收敛修正 float speed = (1.0f - alpha) * 0.0f + alpha * approximatethre * apmtspeedratio; currentvelocity = deltapos.normalized * speed; } else { Vector3 newHVelocity = m_pFSM.syncVelocity; Vector3 oldHVelocity = new Vector3(lastvelocity.x, 0, lastvelocity.z); Vector3 HVelocityDelta = newHVelocity - oldHVelocity; float advance = deltaTime * finalInertiaAcceleration; if (advance > HVelocityDelta.magnitude) { advance = HVelocityDelta.magnitude; } currentvelocity = oldHVelocity + HVelocityDelta.normalized * advance; } } lastvelocity = currentvelocity; CheckMoveForward();//检查是否向前 //-------------------------------------------------------- // 下面算位置 //-------------------------------------------------------- // We always want the movement to be framerate independent. Multiplying by Time.deltaTime does this. if (deltaTime > m_lastFrameDeltaTime * 2.0f || deltaTime < m_lastFrameDeltaTime / 2.0f) //缓冲帧率突变产生的跳跃 { deltaTime = deltaTime * m_pFSM.frameAccFactor + m_lastFrameDeltaTime * (1 - m_pFSM.frameAccFactor); } m_lastFrameDeltaTime = deltaTime; Vector3 currentOffset = currentvelocity * deltaTime; m_pFSM.syncDetalTime += deltaTime; // Find out how much we need to push towards the ground to avoid loosing grouning // when walking down a step or over a sharp change in slope. if (m_pFSM.isHero && !m_pFSM.bControlledBySever) //主角 { if (grounded) //主角贴地 { float pushDownOffset = Mathf.Max(m_pFSM.controller.stepOffset, (new Vector3(currentOffset.x, 0, currentOffset.z)).magnitude); if (float.IsNaN(m_pFSM.controller.stepOffset)) { Debug.LogError(m_pFSM.name + "standing m_pFSM.controller.stepOffset " + m_pFSM.controller.stepOffset); pushDownOffset = (new Vector3(currentOffset.x, 0, currentOffset.z)).magnitude; } currentOffset -= pushDownOffset * Vector3.up; } if (m_pFSM.ShiftEnable) { //if (InputManager.GetKey(KeyCode.LeftShift) || InputManager.GetKey(KeyCode.RightShift))//主角暂时添加加速快捷键以便测试 { currentOffset *= 5.0f; } } } else //非主角 { //Vector3 idealPos = tr.position; //calSyncOffset(currentvelocity, ref currentOffset, ref idealPos); //currentvelocity = * m_pFSM.syncVelocity.magnitude; Vector3 dir = (m_pFSM.syncPosition - tr.position).normalized; currentvelocity = dir * currentvelocity.magnitude; currentOffset = currentvelocity * deltaTime; if (currentOffset.sqrMagnitude < 0.001f) { currentvelocity = Vector3.zero; } } //-------------------------------------------------------- // 下面更新animator //-------------------------------------------------------- if (m_pFSM.animatorCtrl.ana != null && m_pFSM.animatorCtrl.ana.isInitialized) { Vector3 planeVel = new Vector3(currentvelocity.x, 0, currentvelocity.z); if (planeVel.sqrMagnitude > 0.0001f) { m_pFSM.animatorCtrl.ana.SetBool("isMoving", true); bIsMoving = true; } else { m_pFSM.animatorCtrl.ana.SetBool("isMoving", false); bIsMoving = false; } //取移动速度相对于主角面向的向前和向左的标量 float fRight = Vector3.Dot(currentvelocity, tr.right); float fForward = Vector3.Dot(currentvelocity, tr.forward); if (currentvelocity.sqrMagnitude < 0.0036f) { //同步过来的速度为0之后,点乘还会有误差,造成轻微移动动作 fRight = 0.0f; fForward = 0.0f; } if (Mathf.Abs(fRight) < 0.06f) { fRight = 0.0f; } if (Mathf.Abs(fForward) < 0.06f) { fForward = 0.0f; } //移动速度考虑了服务器速度和基本速度的比率后,按服务器速度算animator参数值 if (m_pFSM.maxForwardSpeed > 0) { if (fForward >= 0.0f) { fForward = fForward / m_pFSM.maxForwardSpeed; } else { fForward = fForward / m_pFSM.maxRunBackwardSpeed; } } else { if (fForward > 0.0f) { fForward = fForward / m_pFSM.creaturePropety.runSpeed_Forward; } else { fForward = fForward / m_pFSM.creaturePropety.runSpeed_Back; } } if (m_pFSM.maxRunSidewaySpeed > 0) { fRight = fRight / m_pFSM.maxRunSidewaySpeed; } else { fRight = fRight / m_pFSM.creaturePropety.runSpeed_LeftRight; } //fForward = fForward / m_pFSM.basicForwardSpeed; //fRight = fRight / m_pFSM.basicSidewaysSpeed; //速度和动作不能成正比,线性的话速度小的时候容易滑步,这里利用开根做了一次非线性变换 //if (fForward >= 0.0f) //{ // fForward = Mathf.Sqrt(fForward); //} //else //{ // fForward = -Mathf.Sqrt(-fForward); //} //if (fRight >= 0.0f) //{ // fRight = Mathf.Sqrt(fRight); //} //else //{ // fRight = -Mathf.Sqrt(-fRight); //} if (m_pFSM.animatorCtrl.ana != null && m_pFSM.animatorCtrl.ana.isInitialized) { m_pFSM.animatorCtrl.ana.SetFloat(hashid_moveright, fRight); m_pFSM.animatorCtrl.ana.SetFloat(hashid_moveforward, fForward); m_pFSM.animatorCtrl.ana.SetFloat(hashid_velocity, currentvelocity.magnitude); } if (m_pFSM.animatorCtrl.anb != null && m_pFSM.animatorCtrl.anb.isInitialized) { m_pFSM.animatorCtrl.anb.SetFloat(hashid_moveright, fRight); m_pFSM.animatorCtrl.anb.SetFloat(hashid_moveforward, fForward); } //m_pFSM. updateMovingAnimSpeed(); //动画速率用maxSpeed和basicSpeed比率控制,这里暂时不控制 //float speedScale = Mathf.Max(Mathf.Abs(fRight), Mathf.Abs(fForward)); //if (speedScale > 1.0f) //{ // speedScale = (speedScale - 1.0f) * 0.3f + 1.0f; //张嘉华提供的跑路速度和跑路动画速度关系 // m_pFSM.animator.speed = speedScale; //} //else //{ // m_pFSM.animator.speed = 1.0f; //} } //-------------------------------------------------------- // 下面更新transform //-------------------------------------------------------- // Save lastPosition for velocity calculation. Vector3 oldPosition = tr.position; float curtime = Time.time; if (m_pFSM.isHero && !m_pFSM.bControlledBySever)//是主角,都用耗时的物理行走方法 { m_pFSM.collisionFlags = m_pFSM.controller.Move(currentOffset); ++heroMoveTimes; } else//非主角 { float pos_dis = (m_pFSM.syncPosition - tr.transform.position).magnitude; if (m_pFSM.syncVelocity.sqrMagnitude < 0.01f && m_pFSM.animatorCtrl.bDoingAttackMove) { pos_dis = 0.0f; //正在利用动作控制位移,就不按同步包移动了 } if (physenable && pos_dis > approximatethre) //跟同步位置差距较大时用耗时的物理行走方法 { m_pFSM.collisionFlags = m_pFSM.controller.Move(currentOffset); } else if (pos_dis > 0.01f) //否则用较小耗时的渐趋逼近公式 { Vector3 deltapos = m_pFSM.syncPosition - tr.transform.position; Vector3 curPos; if (deltapos.sqrMagnitude > currentOffset.sqrMagnitude) { curPos = tr.transform.position + currentOffset; } else { curPos = tr.transform.position * 0.5f + m_pFSM.syncPosition * 0.5f; } float GroundedCheckDistance = 5.0f; curPos = BaseStateMachine.CorrectPosFromPhysic(curPos, m_pFSM.creaturePropety.CreatureHeightInMeters + 0.1f, GroundedCheckDistance); tr.transform.SetPosition(curPos); } else { } } if (m_pFSM.isHero && !m_pFSM.bControlledBySever)//主角不用平滑角度 { } else//非主角才平滑角度角度 { float angle_dis = (m_pFSM.syncAngle - tr.transform.eulerAngles).magnitude; if (angle_dis > 0.1f) //角度差距较大时采用逼近公式 { Vector3 newangle; newangle.x = Mathf.LerpAngle(tr.eulerAngles.x, m_pFSM.syncAngle.x, 0.2f); newangle.y = Mathf.LerpAngle(tr.eulerAngles.y, m_pFSM.syncAngle.y, 0.2f); newangle.z = Mathf.LerpAngle(tr.eulerAngles.z, m_pFSM.syncAngle.z, 0.2f); tr.eulerAngles = newangle; } } lastupdatetime = curtime; lastoffset = currentOffset; //最后算完才上报 if (sendSync != MoveSyncFlag.NOT_2_SERVER && (m_pFSM.isHero && !m_pFSM.bControlledBySever)) { int curTick = System.Environment.TickCount; m_pFSM.syncTick = curTick; Vector3 sendVelocity = new Vector3(currentvelocity.x, 0.0f, currentvelocity.z); m_pFSM.syncVelocity = sendVelocity; m_pFSM.syncPosition = tr.position; m_pFSM.syncAngle = tr.eulerAngles; Send_Sync_Position(sendSync); } else if (heroMoveTimes >= 4) { Vector3 sendVelocity = new Vector3(currentvelocity.x, 0.0f, currentvelocity.z); updatePosWithoutSend(sendVelocity, tr.position, tr.eulerAngles); heroMoveTimes = 0; } }
// 更新状态逻辑 public void Update() { deltaTime = Time.deltaTime; if (deltaTime < 0.001f) { Debug.LogError("deltaTime=" + deltaTime); return; } uint tick = GameLogicAPI.getTickCount(); bool oldGrounded = isGrounded; isGrounded = IsGroundedTest(); //测试是否在空中 float Vy = getVelocity().y; Vector3 inputVelocity = ApplyInputVelocityChange(getVelocity()); //根据键盘输入调整速度 Vector3 velocity = Vector3.zero; if (m_pFSM.isHero && !m_pFSM.bControlledBySever) { velocity = inputVelocity; } else { velocity = m_pFSM.syncVelocity; } velocity.y = Vy; //处理在空中的情况 if (isGrounded && !m_bIsGlideRuning) { //刚到地面,开始着陆的处理 if (!m_bIsLanding) { //切换动作 if (m_pFSM.animator) { m_pFSM.animator.SetBool(hashid_isLanding, true); m_pFSM.animator.SetBool(hashid_isGlide, false); m_pFSM.animator.SetBool(hashid_FlyDown, false); } m_bIsLanding = true; //正在着陆 } else //着陆后的处理 { //结束本状态,切换到新状态 velocity.y = Mathf.Min(0, velocity.y) - m_pFSM.currentGravity * deltaTime; setVelocity(velocity); m_pFSM.maxGlideSpeed = oldGlideSpeed; m_pFSM.isGlideState = false; m_pFSM.ChangeState((int)EntityState.Standing, IntPtr.Zero); } } else //这里包含两个状态:起跳 -> 最高点 ->落地 { if (velocity.y <= 0) { velocity.y = m_Velocity.y - m_pFSM.glideDownSpeedAcceleration * deltaTime; } else { velocity.y = m_Velocity.y - m_pFSM.currentGravity * deltaTime; } // Make sure we don't fall any faster than maxFallSpeed. This gives our character a terminal velocity. velocity.y = Mathf.Max(velocity.y, m_pFSM.SkinConfig == null ? -15 : -m_pFSM.SkinConfig.maxFallSpeed); setVelocity(velocity); //velocity.y = Mathf.Min(velocity.y, m_pFSM.SkinConfig == null ? 15 : m_pFSM.SkinConfig.maxFallSpeed); } if (m_bIsGlideRuning) { Vector3 jumpDir = Vector3.up; startUpTick = 0; velocity.y = 0; m_pFSM.animator.SetBool(hashid_isGlide, true); //添加y轴分量的初始速度,以后做自由落体运动 //velocity += jumpDir * CalculateJumpVerticalSpeed(m_pFSM.glideUpHeight);// m_pFSM.glideUpHeight); m_bIsGlideRuning = false; m_bIsJumping = false; isGrounded = false; m_pFSM.groundNormal = Vector3.zero; setVelocity(velocity); } //同步? if (m_pFSM.isHero && !m_pFSM.bControlledBySever) { m_pFSM.syncVelocity = velocity; // 判断本地的模拟坐标和真实坐标的差别, 只有达到一定阀值才需要同步 // 暂时在行走过程中200ms同步一次 int curTick = System.Environment.TickCount; MoveSyncFlag sendSync = MoveSyncFlag.NOT_2_SERVER; if (curTick >= m_lastSyncTick + 5000) //5秒强制同步一次 { sendSync = MoveSyncFlag.TO_SERVER; } else if ((m_lastSyncVel.sqrMagnitude > 0.0001f && m_pFSM.syncVelocity.sqrMagnitude < 0.0001f) || (m_lastSyncVel.sqrMagnitude < 0.0001f && m_pFSM.syncVelocity.sqrMagnitude > 0.0001f))//启动和站立强制同步一次 { sendSync = MoveSyncFlag.TO_BROADCAST; } else //每200毫秒根据速度或者移动距离考虑是否同步一次 { Vector3 velSub = m_lastSyncVel - m_pFSM.syncVelocity; Vector3 posSub = tr.position - m_lastSyncPos; if ((curTick >= m_lastSyncTick + 200) && (velSub.sqrMagnitude > 0.01f || posSub.sqrMagnitude > 1.0f)) { sendSync = MoveSyncFlag.TO_SERVER; } } if (sendSync != MoveSyncFlag.NOT_2_SERVER && (m_pFSM.isHero && !m_pFSM.bControlledBySever)) { m_pFSM.syncVelocity.y = 0.0f; // 跳跃的同步包y方向速度都为0,由实际跳跃产生。 Send_Sync_Position(sendSync); m_lastSyncTick = curTick; m_lastSyncVel = m_pFSM.syncVelocity; m_lastSyncPos = tr.position; } } //移动characterController Vector3 currentMovementOffset = velocity * deltaTime; // Find out how much we need to push towards the ground to avoid loosing grouning // when walking down a step or over a sharp change in slope. //计算跨步的距离 float pushDownOffset = Mathf.Max(m_pFSM.controller.stepOffset, (new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z)).magnitude); if (float.IsNaN(m_pFSM.controller.stepOffset)) { Debug.LogError(m_pFSM.name + " jumping controller.stepOffset error" + m_pFSM.controller.stepOffset); pushDownOffset = (new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z)).magnitude; } //向下偏移,处理下楼梯? if (isGrounded) { currentMovementOffset -= pushDownOffset * Vector3.up; } //真正的移动 m_pFSM.collisionFlags = m_pFSM.controller.Move(currentMovementOffset); //处理消息发送 //.... }
private void UpdateFunction() { deltaTime = Time.deltaTime; if (deltaTime < 0.001f) { Debug.LogError("deltaTime=" + deltaTime); return; } if (m_pFSM.moveCtrl.isCharge()) { if (m_pFSM.animator != null) { m_pFSM.animator.SetFloat(hashid_moveforward, 0); m_pFSM.animator.SetFloat(hashid_moveright, 0); m_pFSM.animator.SetFloat(hashid_velocity, 0); m_pFSM.animator.SetBool(hashid_isMoving, false); } return; } Vector3 velocity = m_Velocity; m_pFSM.syncDetalTime += deltaTime; if (!m_pFSM.isHero || m_pFSM.bControlledBySever) { velocity = m_pFSM.syncVelocity; calSyncVel(tr.position, ref velocity); } if (float.IsNaN(velocity.x) || float.IsNaN(velocity.y) || float.IsNaN(velocity.z)) { Debug.LogError(m_pFSM.name + " jumping (Line226) velocity error " + velocity); velocity = Vector3.zero; } Vector3 inputVelocity = ApplyInputVelocityChange(velocity); //根据键盘输入调整速度,一般在平地才用 if (float.IsNaN(inputVelocity.x) || float.IsNaN(inputVelocity.y) || float.IsNaN(inputVelocity.z)) { Debug.LogError(m_pFSM.name + "jumping inputVelocity is " + inputVelocity); inputVelocity = Vector3.zero; } if (m_bIsLanding && (m_pFSM.isHero && !m_pFSM.bControlledBySever)) { // Update velocity based on input velocity = inputVelocity; //Trace.Log("Landing vel="+m_Velocity.ToString()+"-->"+velocity.ToString()); } else if (m_pFSM.dodge) { if (m_pFSM.isHero && !m_pFSM.bControlledBySever) { velocity = inputVelocity; } else { velocity = m_pFSM.syncVelocity; } } else { //在空中的时候,只稍微考虑一下,为了撞墙后直接跳跃也能爬墙,而不是垂直跳 Vector3 inputOffset = inputVelocity; inputOffset.y = 0.0f; Vector3 jumpOffset = velocity; jumpOffset.y = 0.0f; if (inputOffset.magnitude / 2 > jumpOffset.magnitude) { Vector3 combineOffset = jumpOffset * 0.95f + inputOffset * 0.05f; velocity.x = combineOffset.x; velocity.z = combineOffset.z; } if (m_pFSM.isGlideState) { Vector3 pos = m_pFSM.transform.position + new Vector3(0, 0.1f, 0); if (Mathf.Abs(pos.y - glideLastHitPoint.y) > 0.5f) { RaycastHit hitInfo; Ray PointToGroundRay = new Ray(pos, new Vector3(0, -1, 0)); Physics.Raycast(PointToGroundRay, out hitInfo, 100); if ((pos.y - hitInfo.point.y) > m_pFSM.controller.height + 0.6f) { m_pFSM.ChangeGlideState(); } else { glideLastHitPoint = pos; } } } } if (m_pFSM.isHero && !m_pFSM.bControlledBySever) { m_pFSM.syncVelocity = velocity; // 判断本地的模拟坐标和真实坐标的差别, 只有达到一定阀值才需要同步 // 暂时在行走过程中200ms同步一次 int curTick = System.Environment.TickCount; MoveSyncFlag sendSync = MoveSyncFlag.NOT_2_SERVER; if (curTick >= m_lastSyncTick + 5000) //5秒强制同步一次 { sendSync = MoveSyncFlag.TO_SERVER; } else if ((m_lastSyncVel.sqrMagnitude > 0.0001f && m_pFSM.syncVelocity.sqrMagnitude < 0.0001f) || (m_lastSyncVel.sqrMagnitude < 0.0001f && m_pFSM.syncVelocity.sqrMagnitude > 0.0001f))//启动和站立强制同步一次 { sendSync = MoveSyncFlag.TO_BROADCAST; } else //每200毫秒根据速度或者移动距离考虑是否同步一次 { Vector3 velSub = m_lastSyncVel - m_pFSM.syncVelocity; Vector3 posSub = tr.position - m_lastSyncPos; if ((curTick >= m_lastSyncTick + 200) && (velSub.sqrMagnitude > 0.01f || posSub.sqrMagnitude > 1.0f)) { sendSync = MoveSyncFlag.TO_SERVER; } } if (sendSync != MoveSyncFlag.NOT_2_SERVER && (m_pFSM.isHero && !m_pFSM.bControlledBySever)) { m_pFSM.syncVelocity.y = 0.0f; // 跳跃的同步包y方向速度都为0,由实际跳跃产生。 Send_Sync_Position(sendSync); m_lastSyncTick = curTick; m_lastSyncVel = m_pFSM.syncVelocity; m_lastSyncPos = tr.position; } } // We copy the actual velocity into a temporary variable that we can manipulate. // Apply gravity and jumping force velocity = ApplyGravityAndJumping(velocity); if (float.IsNaN(velocity.x) || float.IsNaN(velocity.y) || float.IsNaN(velocity.z)) { Debug.LogError(m_pFSM.name + " jumping velocity (line 304) error" + velocity); velocity = Vector3.zero; } if (m_bIsLanding && m_pFSM.animator != null) { Vector3 planeVel = new Vector3(velocity.x, 0, velocity.z); if (planeVel.sqrMagnitude > 0.0f) { m_pFSM.animator.SetBool(hashid_isMoving, true); } else { m_pFSM.animator.SetBool(hashid_isMoving, false); } //取移动速度相对于主角面向的向前和向左的标量 float fRight = Vector3.Dot(velocity, tr.right); float fForward = Vector3.Dot(velocity, tr.forward); //移动速度考虑了服务器速度和基本速度的比率后,按服务器速度算animator参数值 if (m_pFSM.maxForwardSpeed > 0) { fForward = fForward / m_pFSM.maxForwardSpeed; } else { fForward = fForward / m_pFSM.creaturePropety.runSpeed_Forward; } if (m_pFSM.maxRunSidewaySpeed > 0) { fRight = fRight / m_pFSM.maxRunSidewaySpeed; } else { fRight = fRight / m_pFSM.creaturePropety.runSpeed_LeftRight; } //fRight = fRight / m_pFSM.basicSidewaysSpeed; ////速度和动作不能成正比,线性的话速度小的时候容易滑步,这里利用开根做了一次非线性变换 //if (fForward >= 0.0f) //{ // fForward = fForward / m_pFSM.basicForwardSpeed; // fForward = Mathf.Sqrt(fForward); //} //else //{ // fForward = fForward / m_pFSM.basicBackwardSpeed; // fForward = -Mathf.Sqrt(-fForward); //} //if (fRight >= 0.0f) //{ // fRight = Mathf.Sqrt(fRight); //} //else //{ // fRight = -Mathf.Sqrt(-fRight); //} m_pFSM.animator.SetFloat(hashid_moveright, fRight); m_pFSM.animator.SetFloat(hashid_moveforward, fForward); m_pFSM.animator.SetFloat(hashid_velocity, velocity.magnitude); //动画速率用maxSpeed和basicSpeed比率控制,这里暂时不控制 //float speedScale = Mathf.Max(Mathf.Abs(fRight), Mathf.Abs(fForward)); //if (speedScale > 1.0f) //{ // speedScale = (speedScale - 1.0f) * 0.3f + 1.0f; //张嘉华提供的跑路速度和跑路动画速度关系 // m_pFSM.animator.speed = speedScale; //} //else //{ // m_pFSM.animator.speed = 1.0f; //} } // Moving platform support Vector3 moveDistance = Vector3.zero; // Save lastPosition for velocity calculation. Vector3 lastPosition = tr.position; // We always want the movement to be framerate independent. Multiplying by Time.deltaTime does this. Vector3 currentMovementOffset = velocity * deltaTime; // Find out how much we need to push towards the ground to avoid loosing grouning // when walking down a step or over a sharp change in slope. float pushDownOffset = Mathf.Max(m_pFSM.controller.stepOffset, (new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z)).magnitude); if (float.IsNaN(m_pFSM.controller.stepOffset)) { Debug.LogError(m_pFSM.name + " jumping controller.stepOffset error" + m_pFSM.controller.stepOffset); pushDownOffset = (new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z)).magnitude; } if (grounded) { currentMovementOffset -= pushDownOffset * Vector3.up; } m_pFSM.collisionFlags = m_pFSM.controller.Move(currentMovementOffset); //先暂时关闭拉扯位置,保证非主角跳跃平滑 //if (!m_pFSM.isHero) //前面都是自己算的运动轨迹,非主角考虑同步位置的问题,避免连续跳跃(例如轻功)时位置偏移过大 //{ // Vector3 syncOffset = m_pFSM.syncPosition - tr.position; // syncOffset.y = 0.0f; // if (syncOffset.sqrMagnitude > 0.01f) // { // m_pFSM.controller.Move(syncOffset * 0.8f); // } //} // Calculate the velocity based on the current and previous position. // This means our velocity will only be the amount the character actually moved as a result of collisions. Vector3 oldHVelocity = new Vector3(velocity.x, 0, velocity.z); m_Velocity = (tr.position - lastPosition) / deltaTime; Vector3 newHVelocity = new Vector3(m_Velocity.x, 0, m_Velocity.z); // The CharacterController can be moved in unwanted directions when colliding with things. // We want to prevent this from influencing the recorded velocity. //if (oldHVelocity == Vector3.zero) if (oldHVelocity.sqrMagnitude < 0.0001f) { m_Velocity = new Vector3(0, m_Velocity.y, 0); } else { float projectedNewVelocity = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude; m_Velocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + m_Velocity.y * Vector3.up; } if (m_Velocity.y < velocity.y - 0.001) { if (m_Velocity.y < 0) { // Something is forcing the CharacterController down faster than it should. // Ignore this m_Velocity.y = velocity.y; } } // We were grounded but just loosed grounding if (grounded && !IsGroundedTest()) { grounded = false; //m_pFSM.SendMessage("OnFall", SendMessageOptions.DontRequireReceiver); // We pushed the character down to ensure it would stay on the ground if there was any. // But there wasn't so now we cancel the downwards offset to make the fall smoother. tr.position += pushDownOffset * Vector3.up; } // We were not grounded but just landed on something else if (!grounded && IsGroundedTest()) { grounded = true; if (m_pFSM.animator) { m_pFSM.animator.SetBool("isLanding", true); Vector3 moveDir = m_pFSM.inputMoveDirection; Vector3 planeVel = new Vector3(moveDir.x, 0, moveDir.z); if (planeVel.sqrMagnitude > 0.0f) { m_pFSM.animator.SetBool(hashid_isMoving, true); } else { m_pFSM.animator.SetBool(hashid_isMoving, false); } } m_bIsLanding = true; m_bIsJumping = false; m_bLongJump = false; //float maxFallSpeed = m_pFSM.SkinConfig == null ? 15 : m_pFSM.SkinConfig.maxFallSpeed; //int landingSpeed = (int)(-velocity.y); float fallHeight = startHeight - m_pFSM.transform.position.y; //if (landingSpeed > maxFallSpeed / 2.0f) //着陆大于最大速度的一半,可能需要计算伤害,上报逻辑层 if (m_pFSM.isHero && fallHeight > 5.0f) //着陆时落差大于5米,则上报逻辑层 { cmd_creature_act_landspeed data = new cmd_creature_act_landspeed(); //data.fValue = landingSpeed; data.fValue = fallHeight; IntPtrHelper helper = new IntPtrHelper(); int len = Marshal.SizeOf(data); IntPtr ptr = helper.toPtr <cmd_creature_act_landspeed>(ref data); int eventID = (int)EntityLogicDef.ENTITY_CMD_LANDING_SPEED; GameLogicAPI.onEntityEvent(m_pFSM.entityID, eventID, len, "", ptr, len); if (m_pFSM.showLog) { Trace.Log("Big Landing! fallHeight=" + fallHeight.ToString()); } } if (m_pFSM.creaturePropety.effectIDForLand > 0) { m_pFSM.creaturePropety.Master.LightingEffectManager.BindLighting(m_pFSM.creaturePropety.effectIDForLand); } //m_pFSM.SendMessage("OnLand", SendMessageOptions.DontRequireReceiver); } if (m_bIsLanding == false) { m_pFSM.groundNormal = Vector3.zero; } }