Perfomance of trace rays

Please post any questions about developing your plugin here. Please use the search function before posting!
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Perfomance of trace rays

Postby InvisibleSoldiers » Thu Feb 27, 2020 7:03 pm

Can I increase performance of trace rays in SP? I need to do many traces in loop for iterating over whole circle and check if any player there.

Sample code:

Syntax: Select all

trace_filter = TraceFilterSimple((player, ))
game_trace = GameTrace()

for i in range(1000):
engine_trace.trace_ray(
Ray(start_pos, start_pos + direction * 8192.0),
ContentMasks.SHOT,
trace_filter,
game_trace
)
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: Perfomance of trace rays

Postby VinciT » Sat Feb 29, 2020 5:04 am

I'm assuming you're using trace rays to check for walls?
If that's the case, you can avoid using a lot of rays by getting the distance between the player and the starting position and seeing if it's within a certain radius before checking for walls.

Syntax: Select all

# ../get_players_in_sphere/get_players_in_sphere.py

# Source.Python
from engines.trace import (ContentMasks, engine_trace, GameTrace, Ray,
TraceFilterSimple)
from filters.players import PlayerIter
from mathlib import Vector


HEIGHT_OFFSET = Vector(0, 0, 32)


def get_players_in_sphere(position, radius, wall_check=True):
_players = []

# Go through all the Players.
for player in PlayerIter():
# Get the Player center.
player_center = player.origin + HEIGHT_OFFSET
# Calculate the distance between the center of the sphere and the
# center of the Player.
distance = position.get_distance(player_center)

# Is the Player within the radius?
if distance <= radius:
# Should we check for walls?
if wall_check:
# Create and fire a new trace ray from the center of the sphere
# to the center of the Player.
trace = GameTrace()
engine_trace.trace_ray(
Ray(position, player_center),
ContentMasks.ALL,
TraceFilterSimple(),
trace
)

# Did we hit a wall?
if trace.did_hit_world():
# Skip this Player.
continue

debug_line(position, trace.end_position)

_players.append(player)

return _players


# Debug
import effects
from commands import CommandReturn
from commands.client import ClientCommand
from engines.precache import Model
from filters.recipients import RecipientFilter
from players.dictionary import PlayerDictionary


beam_model = Model('sprites/laserbeam.vmt')
player_instances = PlayerDictionary()


def debug_line(start, end, color=(255, 255, 255)):
effects.beam(RecipientFilter(),
start=start,
end=end,
parent=False,
life_time=5,
red=color[0],
green=color[1],
blue=color[2],
alpha=175,
speed=1,
model_index=beam_model.index,
start_width=0.4,
end_width=0.4)


# Usage: get_players_in_sphere <radius>
@ClientCommand('get_players_in_sphere')
def radius_command(command, index):
player = player_instances[index]
try:
radius = float(command[1])
except IndexError:
return CommandReturn.BLOCK

players = get_players_in_sphere(player.view_coordinates, radius, True)

if players:
for player in players:
print(player.name)

return CommandReturn.BLOCK
ImageImageImageImageImage
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: Perfomance of trace rays

Postby InvisibleSoldiers » Mon Mar 02, 2020 2:44 pm

No. Player shot, but missed, I want to trace ray the whole circle relative to the shot to find out the accuracy of the shot relative to near enemies.
Player shoot with some eye angle (QAngle), I have direction(get_angle_vectors), length(8192) of the shoot, I have start location of shot(eye_location), but to find out the accuracy I need to ray trace with new QAngle which will differ with every raytrace in loop. It is potential eye_angle with whom he could shoot and hit a enemy.

For example:

Syntax: Select all

shoot_eye_angle - QAngle(80.0, 65.0, 0.0)
shoot_pos - Vector(?, ?, ?)

Init loop:
for i in range(100) {
shoot_eye_angle.x += 0.04

forward = Vector()
direction = shoot_eye_angle.get_angle_vectors(forward, None, None)

engine_trace.trace_ray(
Ray(shoot_pos, shoot_pos + direction * 8192.0),
ContentMasks.SHOT,
trace_filter,
game_trace
)

if 0 < game_trace.entity_index < 65 {
accuracy_percent = 100 - i
break
}
}


It is only by vertically but I think the meaning is clear.
At each iteration in the loop, angle from player potentially eye_angle shoot sum with step angle(0.04), the further we go the worse the accuracy.

Horizontal and vertical can still be endured, but when there are full circle with some trigonometry server freezes.
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

Re: Perfomance of trace rays

Postby Hymns For Disco » Thu Mar 12, 2020 6:33 am

First you have said that you want to trace a circle to find any near player, then you said you are trying to find the "accuracy of the shot". What is the end goal here? If you want to find players that are nearby the shot angle, you can work that without traces (or maybe just a single trace per player to see if they are easily visible).

Also, if our server is freezing trying to do the full circle, it is possible you have a logic error, rather than a performance bottleneck. Presumably your 100 sample example here works? Whatever algorithm you have implemented for tracing the full circle, you should be able to adjust the number of samples there, and set it to 100 also. Running a few hundred trigonometry functions and/or traces shouldn't be enough to kill a server. I've run sourcemod plugins that trace ~100 times per tick without noticing any performance effects.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 23 guests