升级Line2D循环检测器至4.0版本遇三类问题求助
背景说明
此脚本由Theraot于数年前开发,近期尝试升级优化后虽能勉强运行,但存在三类异常问题:
问题1:线段长度修复后出现卡顿
原脚本存在鼠标移动过快生成超长线段的问题,我通过计算所需线段数量、创建插值点修复后,出现卡顿滞后异常。相关代码如下:
var distance = Points[-2].distance_to(Mouse_Position) # Check if the current distance is greater then segment distance if distance > Segment_Distance: var distanceDifference = distance - Segment_Distance var segmentsToAdd = int(distanceDifference / Segment_Distance) # Want to add segments for when the mouse is far away from the second to last point # but I am not sure what to do, I attempted using a interpolated point # but it glitches out for i in range(segmentsToAdd): var newPoint = Points[-2] + (Mouse_Position - Points[-2]).normalized() * Segment_Distance Points.append(newPoint) Create_Segment(Points[-2], newPoint) Points[-1] = Mouse_Position Update_Segment(Points[-2], Mouse_Position) else: # if the distance is not greater then we simply update the last position of the point to mouse Points[-1] = Mouse_Position Update_Segment(Points[-2], Mouse_Position)
问题2:循环创建后残留线段且初始点异常
创建循环并生成新初始点时,会残留多余线段,且新初始点可能缺失或未绘制。对Process_Loop函数逻辑理解不足,无法排查问题。
问题3:循环创建时偶发点跳至(0,0)
创建循环时,偶尔会出现某线段点跳至(0,0)的情况,原因不明。
完整脚本
以下完整脚本可直接粘贴到任意Node2D节点上运行:
extends Node2D # Variables var Line : Line2D # Holds the line created var Line_Width : int = 10 # We use this for collision thickness var Segment_Distance : int = 50 # The Distance of each segment also how we create a new one var Segments : Node2D # Creates a segment when enough distance is made also holds area2Ds var Loop : Node2D # Holds the first created loop until a new loop is created var Points : PackedVector2Array = PackedVector2Array() # Holds all the points for the line2D var Max_Points : int = 50 # To stop having multiple points on the screen func _ready() -> void: # Create Nodes to hold each part of the line loop detection Line = Line2D.new() Line.name = "Line" Line.width = Line_Width add_child(Line) Segments = Node2D.new() Segments.name = "Segments" add_child(Segments) Loop = Node2D.new() Loop.name = "Loop" add_child(Loop) func _process(delta: float) -> void: if Input.is_action_pressed("Left_Click"): Process_Line(get_global_mouse_position()) if Input.is_action_just_released("Left_Click"): Clear_All() func Process_Line(Mouse_Position: Vector2) -> void: # Get the size of points var Point_Count = Points.size() if Point_Count == 0: # Checks if its 0, we add 2 points for the start and current position Points.append(Mouse_Position) Points.append(Mouse_Position) Create_Segment(Mouse_Position, Mouse_Position) # Create a segment to connect area2D elif Point_Count == 1: Points.append(Mouse_Position) Create_Segment(Points[-2], Mouse_Position) elif Point_Count > Max_Points: Clear(Point_Count - Max_Points) else: var distance = Points[-2].distance_to(Mouse_Position) # Check if the current distance is greater then segment distance if distance > Segment_Distance: var distanceDifference = distance - Segment_Distance var segmentsToAdd = int(distanceDifference / Segment_Distance) # Want to add segments for when the mouse is far away from the second to last point # but I am not sure what to do, I attempted using a interpolated point # but it glitches out for i in range(segmentsToAdd): var newPoint = Points[-2] + (Mouse_Position - Points[-2]).normalized() * Segment_Distance Points.append(newPoint) Create_Segment(Points[-2], newPoint) Points[-1] = Mouse_Position Update_Segment(Points[-2], Mouse_Position) else: # if the distance is not greater then we simply update the last position of the point to mouse Points[-1] = Mouse_Position Update_Segment(Points[-2], Mouse_Position) # Apply the points array to the line2D points Line.points = Points # What does the loop detection currently buggy. Process_Loop() func Create_Segment(start: Vector2, end: Vector2) -> void: # Get the rotation of the points var points = rotated_rectangle_points(start, end, Line_Width) var segment = Area2D.new() segment.add_to_group("Player_Looper") # Add segment to a group to detect stuff var collision = create_collision_polygon(points) segment.add_child(collision) Segments.add_child(segment) func Update_Segment(start: Vector2, end: Vector2) -> void: var points = rotated_rectangle_points(start, end, Line_Width) var segment = Segments.get_child(Segments.get_child_count() - 1) as Area2D var collision = segment.get_child(0) as CollisionPolygon2D collision.set_polygon(points) static func rotated_rectangle_points(start: Vector2, end: Vector2, width: float) -> Array: var diff = end - start var normal = diff.rotated(TAU / 4).normalized() var offset = normal * width * 0.5 return [start + offset, start - offset, end - offset, end + offset] static func create_collision_polygon(points: Array) -> CollisionPolygon2D: var result = CollisionPolygon2D.new() result.set_polygon(points) return result func Process_Loop() -> void: var segments = Segments.get_children() for index in range(segments.size() - 1, 0, -1): var segment = segments[index] var candidates = segment.get_overlapping_areas() for candidate in candidates: var candidate_index = segments.find(candidate) if candidate_index == -1: continue if abs(candidate_index - index) > 1: push_loop(candidate_index, index) Clear(index) return func push_loop(first_index:int, second_index:int) -> void: Clear_Loop() var loop = Area2D.new() var points = Points points.resize(second_index) for point_index in first_index + 1: points.remove_at(0) var collision = create_collision_polygon(points) loop.add_child(collision) Loop.add_child(loop) func Clear_All() -> void: # Clears the points and segments and also clear loops Clear(Points.size()) Clear_Loop() func Clear(index) -> void: # Loop through the points array and remove each one based on index for _clear in range(index): if Points.size() > 0: Points.remove_at(0) # Get the current segments and also remove each segment var segments = Segments.get_children() for i in range(index): if segments.size() > 0: Segments.remove_child(segments[0]) segments[0].queue_free() segments.remove_at(0) Line.points = Points func Clear_Loop() -> void: for loop in Loop.get_children(): if is_instance_valid(loop): loop.queue_free()
内容的提问来源于stack exchange,提问作者Dragon20C
相关产品推荐
相关产品推荐

