Ruby, 139 bytes
Lambda function, takes x and y as arguments and returns a string
->x,y{c=y-2*n=y-(x>y ?1:0)>>1
x+=-c/2*s=[x-n,c*3].max
x<n||x>n*2?'~<.,,>~~':',<..>, '*(x-n)+'<.,.> '*(2*n-x)+"<%s.> "*c%[?,*s-=c/2*3,?,*3]}
If a solution exists, it can be done with all koalas+commapillars or all koalas+crabs.
The principle is to use a minimum of commapillars. If the number is odd, we use 1 commapillar. if even we use 0 commapillars, unless there are more commas than periods, in which case we use 2.
The number of periods used in noncommapillars (crabs + koalas) is necessarily even, and the number of noncommapillars is half (number of periods)-(number of commapillars)
. If there are insufficient commas for all koalas, or too many for all crabs, no solution is possible. Otherwise, we return a solution.
Commented in test program
uses "fail" instead of chameleon for clarity
f=->x,y{c=y-2*n=y-(x>y ?1:0)>>1
#n=noncommapillars=y>>1 as they have 2 periods. c=commapillars=y-2*n, 1 for odd y, 0 for even y.
#if x>y there are too many commas to have 0 commapillars for even y. noncommapillars= y-1 >> 1, so 2 commapillars
x+=-c/2*s=[x-n,c*3].max
# s=number of commas allocated to commapillars. x-n to allow all noncommapillars to be koalas, but at least 3 per commapillar.
#-c/2 == -1 if there are commapillars, 0 if not (Ruby truncates toward -inf). Subtract commas for commapillars from x if necessary
x<n||x>n*2?'fail':',<..>, '*(x-n)+'<.,.> '*(2*n-x)+"<%s.> "*c%[?,*s-=c/2*3,?,*3]}
#if x<n (insufficient commas for all koalas) or x>n*2 (too many for all crabs) return fail. Else...
#return string off crabs, koalas, and (using % operator like sprintf) c commapillars (0..2), the second with 3 commas (if present) and the first with the rest.
10.times{|j|10.times{|i|puts "%-20s %s"%[?.*j+?,*i,f[i,j]]}}
#all x,y from 0..9
Output
, fail
,, fail
,,, fail
,,,, fail
,,,,, fail
,,,,,, fail
,,,,,,, fail
,,,,,,,, fail
,,,,,,,,, fail
. fail
., fail
.,, fail
.,,, <,,,.>
.,,,, <,,,,.>
.,,,,, <,,,,,.>
.,,,,,, <,,,,,,.>
.,,,,,,, <,,,,,,,.>
.,,,,,,,, <,,,,,,,,.>
.,,,,,,,,, <,,,,,,,,,.>
.. fail
.., <.,.>
..,, ,<..>,
..,,, fail
..,,,, fail
..,,,,, fail
..,,,,,, <,,,.> <,,,.>
..,,,,,,, <,,,,.> <,,,.>
..,,,,,,,, <,,,,,.> <,,,.>
..,,,,,,,,, <,,,,,,.> <,,,.>
... fail
..., fail
...,, fail
...,,, fail
...,,,, <.,.> <,,,.>
...,,,,, <.,.> <,,,,.>
...,,,,,, <.,.> <,,,,,.>
...,,,,,,, <.,.> <,,,,,,.>
...,,,,,,,, <.,.> <,,,,,,,.>
...,,,,,,,,, <.,.> <,,,,,,,,.>
.... fail
...., fail
....,, <.,.> <.,.>
....,,, ,<..>, <.,.>
....,,,, ,<..>, ,<..>,
....,,,,, fail
....,,,,,, fail
....,,,,,,, <.,.> <,,,.> <,,,.>
....,,,,,,,, <.,.> <,,,,.> <,,,.>
....,,,,,,,,, <.,.> <,,,,,.> <,,,.>
..... fail
....., fail
.....,, fail
.....,,, fail
.....,,,, fail
.....,,,,, <.,.> <.,.> <,,,.>
.....,,,,,, <.,.> <.,.> <,,,,.>
.....,,,,,,, <.,.> <.,.> <,,,,,.>
.....,,,,,,,, <.,.> <.,.> <,,,,,,.>
.....,,,,,,,,, <.,.> <.,.> <,,,,,,,.>
...... fail
......, fail
......,, fail
......,,, <.,.> <.,.> <.,.>
......,,,, ,<..>, <.,.> <.,.>
......,,,,, ,<..>, ,<..>, <.,.>
......,,,,,, ,<..>, ,<..>, ,<..>,
......,,,,,,, fail
......,,,,,,,, <.,.> <.,.> <,,,.> <,,,.>
......,,,,,,,,, <.,.> <.,.> <,,,,.> <,,,.>
....... fail
......., fail
.......,, fail
.......,,, fail
.......,,,, fail
.......,,,,, fail
.......,,,,,, <.,.> <.,.> <.,.> <,,,.>
.......,,,,,,, <.,.> <.,.> <.,.> <,,,,.>
.......,,,,,,,, <.,.> <.,.> <.,.> <,,,,,.>
.......,,,,,,,,, <.,.> <.,.> <.,.> <,,,,,,.>
........ fail
........, fail
........,, fail
........,,, fail
........,,,, <.,.> <.,.> <.,.> <.,.>
........,,,,, ,<..>, <.,.> <.,.> <.,.>
........,,,,,, ,<..>, ,<..>, <.,.> <.,.>
........,,,,,,, ,<..>, ,<..>, ,<..>, <.,.>
........,,,,,,,, ,<..>, ,<..>, ,<..>, ,<..>,
........,,,,,,,,, <.,.> <.,.> <.,.> <,,,.> <,,,.>
......... fail
........., fail
.........,, fail
.........,,, fail
.........,,,, fail
.........,,,,, fail
.........,,,,,, fail
.........,,,,,,, <.,.> <.,.> <.,.> <.,.> <,,,.>
.........,,,,,,,, <.,.> <.,.> <.,.> <.,.> <,,,,.>
.........,,,,,,,,, <.,.> <.,.> <.,.> <.,.> <,,,,,.>
__int128
and I was too lazy to use a bignum library. Here is the CSV dump: pastebin.com/ght5xkRu the first row and column are the X and Y values \$\endgroup\$