public void Update() { lastPos = pos; //更新绳子物理 if (rope != null) { rope.Update(tentacleIndex != 0 ? tentacle.tChunks[tentacleIndex - 1].pos : tentacle.FloatBase, pos); if (!RopeActive || phase > -1.0 || tentacleIndex > 0 && tentacle.tChunks[tentacleIndex - 1].phase > -1.0 || rope.totalLength > tentacle.idealLength / (double)tentacle.tChunks.Length * 5.0) { rope.Reset(); } } //如果当前Chunk已定相 if (phase == -1.0) { if (phasesToSameLocation > 0 && tentacle.segments[this.currentSegment] == afterPhaseStuckPos) { pos = Utils.RestrictInRect(pos, StuckRect); } //如果是第一个触手节(靠近基座) if (tentacleIndex == 0) { //计算距离基座的方向和距离 Vector2 dir = Utils.DirVec(pos, tentacle.FloatBase); float dist = Vector2.Distance(pos, tentacle.FloatBase); if (RopeActive) { dir = Utils.DirVec(pos, rope.BConnect); dist = rope.totalLength; } //计算收缩长度 =(理想长度 * 撤回因子)/ 触手关节数目 float length = tentacle.idealLength / tentacle.tChunks.Length * Mathf.Lerp(1f, 0.1f, tentacle.retractFac); if (tp.stiff || dist > (double)length) { //更新当前Chunk的Pos、Vel属性 pos -= dir * (length - dist) * (1f - tp.pullAtConnectionChunk); vel -= dir * (length - dist) * (1f - tp.pullAtConnectionChunk); //如果触手属性对生物连接体有拉力:更新连接Chunk的Pos、Vel属性 if (tentacle.connectedChunk != null && tp.pullAtConnectionChunk > 0.0) { if (RopeActive) { dir = Utils.DirVec(rope.AConnect, tentacle.connectedChunk.pos); } tentacle.connectedChunk.pos += dir * (length - dist) * tp.pullAtConnectionChunk; tentacle.connectedChunk.vel += dir * (length - dist) * tp.pullAtConnectionChunk; } } //计算当前拉伸系数 = 理想长度 /( 触手关节数 * 与上一关节距离) stretchedFac = tentacle.idealLength / tentacle.tChunks.Length / Mathf.Max(1f, dist); } //(计算逻辑基本同上) else { //计算与前一触手节的方向和距离 Vector2 dir = Utils.DirVec(pos, tentacle.tChunks[tentacleIndex - 1].pos); float dist = Vector2.Distance(pos, tentacle.tChunks[tentacleIndex - 1].pos); if (RopeActive) { dir = Utils.DirVec(pos, rope.BConnect); dist = rope.totalLength; } float num = tentacle.idealLength / tentacle.tChunks.Length * Mathf.Lerp(1f, 0.1f, tentacle.retractFac); if (tp.stiff || dist > (double)num) { pos -= dir * (num - dist) * (1f - tp.massDeteriorationPerChunk); vel -= dir * (num - dist) * (1f - tp.massDeteriorationPerChunk); if (RopeActive) { dir = Utils.DirVec(rope.AConnect, tentacle.tChunks[tentacleIndex - 1].pos); } tentacle.tChunks[tentacleIndex - 1].pos += dir * (num - dist) * tp.massDeteriorationPerChunk; tentacle.tChunks[tentacleIndex - 1].vel += dir * (num - dist) * tp.massDeteriorationPerChunk; } stretchedFac = tentacle.idealLength / tentacle.tChunks.Length / Mathf.Max(1f, dist); } //StuckPos不等于trail首个位置时,trail首位插入StuckPos if (StuckPos != currentSegmentTrail[0]) { currentSegmentTrail.Insert(0, StuckPos); currentSegmentTrail.RemoveAt(currentSegmentTrail.Count - 1); } //检测撤回关节索引不存在 && 当前Chunk位置和Segment直线不可达 if (tentacle.backtrackFrom == -1 && !tentacle.Visual(tentacle.room.GetTilePosition(pos), tentacle.segments[this.currentSegment])) { tentacle.backtrackFrom = tentacleIndex; } //如果当前触手体存在撤回索引,且当前Chunk索引大于撤回索引 if (tentacle.backtrackFrom != -1 && tentacleIndex >= tentacle.backtrackFrom) { bool flag = false; for (int index = 1; index <= currentSegment && !flag; ++index) { if (!PhysicsUtils.RayTraceTilesForTerrain(tentacle.room, tentacle.room.GetTilePosition(pos), tentacle.segments[index]) && PhysicsUtils.RayTraceTilesForTerrain(tentacle.room, tentacle.room.GetTilePosition(pos), tentacle.segments[index - 1])) { vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[index - 1]) - pos, 20f) * tp.backtrackSpeed / 20f; flag = true; } } if (!flag) { //获取前一触手节位置 Vector2 tentacleBase = tentacle.FloatBase; if (tentacleIndex > 0) { tentacleBase = tentacle.tChunks[tentacleIndex - 1].pos; } //更新当前Chunk速度 =( 矢量距离 * 撤回速度)/ 20f vel += Vector2.ClampMagnitude(tentacleBase - pos, 20f) * tp.backtrackSpeed / 20f; //更新前一Chunk速度 if (tentacleIndex > 0) { tentacle.tChunks[tentacleIndex - 1].vel += Vector2.ClampMagnitude(tentacleBase - pos, 20f) * tp.backtrackSpeed / 20f; } } //当前关联Point不为空 if (!flag && (contactPoint.x != 0 || contactPoint.y != 0)) { //定相尝试次数递增1 ++phaseAttempts; //定相尝试次数 > 触手属性值 if (phaseAttempts > tentacle.tProps.terrainHitsBeforePhase) { //开始定相 PhaseToSegment(); phaseAttempts = 0; } } } //不存在撤回索引 or 撤回索引大于当前Chunk索引 else { phaseAttempts = 0; //瘫软状态 if (tentacle.limp) { //从当前Seg往前遍历 for (int currentSegment = this.currentSegment; currentSegment >= 0; --currentSegment) { //如果当前Chunk位置和Seg视觉可见 if (tentacle.Visual(tentacle.room.GetTilePosition(pos), tentacle.segments[currentSegment])) { if (tentacle.room.GetTile(tentacle.segments[currentSegment].x, tentacle.segments[currentSegment].y - 1).Solid) { vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[currentSegment].x, tentacle.segments[currentSegment].y) - pos, 20f) * 0.005f; break; } vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[currentSegment]) - pos, 20f) * 0.005f; break; } } } //触手非瘫软状态 else { //触手存在抓取目标 if (tentacle.floatGrabDest.HasValue) { //计算抓取目标对Chunk的吸引力 : 修改速度 if (tentacleIndex == tentacle.tChunks.Length - 1) { vel += Vector2.ClampMagnitude(tentacle.floatGrabDest.Value - pos, 20f) * tp.goalAttractionSpeedTip / 20f; } else { vel += Vector2.ClampMagnitude(tentacle.floatGrabDest.Value - pos, 20f) * tp.goalAttractionSpeed / 20f; } } //Chunk速度 对齐Segment vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[currentSegment]) - pos, 20f) * tp.alignToSegmentSpeed / 20f; } } //Clamp速度、更新位置 vel = Vector2.ClampMagnitude(vel, tp.chunkVelocityCap); pos += vel; //与地形发生碰撞、计算碰撞后的位置、速度、碰撞点 if (collideWithTerrain) { lastContactPoint = contactPoint; PhysicsUtils.TerrainCollisionData terrainCollisionData = PhysicsUtils.HorizontalCollision(tentacle.room, PhysicsUtils.SlopesVertically(tentacle.room, PhysicsUtils.VerticalCollision(tentacle.room, new PhysicsUtils.TerrainCollisionData(pos, pos - vel, vel, rad, new IntVector2(0, 0), true)))); contactPoint = terrainCollisionData.contactPoint; pos = terrainCollisionData.pos; vel = terrainCollisionData.vel; } } //如果当前Chunk为定相 else { //定相逐帧计数(后面的数值基本都设置为:15) phase += 1f / tp.segmentPhaseThroughTerrainFrames; //根据当前定相进度,插值改变Pos属性(PhaseFrom->StuckPos) if (phase <= 1.0) { pos = Vector2.Lerp(phaseFrom, tentacle.room.MiddleOfTile(StuckPos), Mathf.Min(1f, phase)); } //速度设置为0 vel *= 0.0f; //定相完成 if (phase >= 1.0) { phase = -1f; if (afterPhaseStuckPos == StuckPos) { ++phasesToSameLocation; } else { phasesToSameLocation = 0; } afterPhaseStuckPos = StuckPos; } //如果是触手关节、且前一触手节未定相 if (tentacleIndex > 0 && tentacle.tChunks[tentacleIndex - 1].phase == -1.0) { //计算与前一触手节的方向和距离 Vector2 dir = Utils.DirVec(pos, tentacle.tChunks[tentacleIndex - 1].pos); float dist = Vector2.Distance(pos, tentacle.tChunks[tentacleIndex - 1].pos); //计算收缩长度 =(理想长度 * 撤回因子)/ 触手关节数目 float length = tentacle.idealLength / tentacle.tChunks.Length * Mathf.Lerp(1f, 0.1f, tentacle.retractFac); if (tp.stiff || dist > (double)length) { //对前一触手节产生影响 tentacle.tChunks[tentacleIndex - 1].pos += dir * (length - dist) * tp.massDeteriorationPerChunk; tentacle.tChunks[tentacleIndex - 1].vel += dir * (length - dist) * tp.massDeteriorationPerChunk; } //计算拉伸系数 stretchedFac = length / dist; } } UpdateDebugSprites(); }