A word of warning with using Decay like this (it bites me EVERY time): decay will produce very large values if you send it triggers that are longer than 1 sample (or 1 control period for kr signals). Even triggering it before it fully decays can produce values >1. This can occasionally be valuable, but it’s easy to get in trouble if you decide later “oh, I’ll trigger this really fast, that’ll be cool” and it blows up.
I believe you’re only having a problem because you’re not sending your \attack and \trig at the same time / in the same message - the attack will only take effect when the envelope is triggered, if it’s received just after a trigger, you’ll be running through the envelope with the old value. This should work:
x = Synth(\a, [\atk, 10]);
x.set(\trig, 1, \atk, 0.01);
You can also modify the control a little by making e.g. your \atk parameter a trigger parameter, e.g. \atk.tr instead of atk.kr - this means when you send it a new value, it outputs that value for 1 sample (a trigger), and then goes back to zero. Then, you could do:
attack = \atk.tr;
Env.perc(Latch.kr(attack, attack), 1).kr(gate:attack); // latch will hold the value when triggered
and simply trigger with x.set(\atk, 1). Though to be totally honest, I would avoid this unless you’re building a really complex synth, because it’s slightly less clear at a glance what’s going on 
Also, there’s a pattern object that encapsulates the “run a synth once, and then send changes to it” - take a look at Pmono. Here’s an example of what that looks like, with a re-triggering envelope and different note values:
(
SynthDef(\envel, {
var sig, env, freq;
// Perc envelope, with retriggering.
env = Env.perc(\attack.kr(0.01), \release.kr(4), curve:[-4, -20]).kr(gate:\trig.tr);
// Two freqs, slightly detuned, with a lag to smooth changes
freq = \freq.kr.lag(0.03);
freq = [
freq,
freq * env.linlin(0, 1, 1.005, 1.02)
];
// Two oscillators, with a fade parameter
sig = XFade2.ar(
LFCub.ar(freq),
LFSaw.ar(freq) * 0.2,
\osc.kr(-1).lag(0.5).poll
);
// Apply envelope and a low-pass
sig = env * sig;
sig = LPF.ar(sig, env.linexp(0, 1, 200, 9000));
// ... and some delay, with a param for delay time
// (and nice clicksssss)
sig = sig + CombC.ar(sig, 4, \delay.kr(2)/[4, 3], 4);
Out.ar(\out.kr(0), sig * [1, 1]);
}).add;
Pdef(\e1, Pmono(
\envel,
\trig, 1,
\delay, Prand([2, 4], inf),
\dur, Prand([1, Pseq([1/3], 4)], inf),
\attack, Prand([0.01, 0.1, 0.5], inf),
\osc, Prand([-1, 0, 1], inf),
\degree, Pseq([
Pseq([0, 1, 3, -2], 4),
Pseq([0, 2, 5, -1], 4)
], inf)
)).play;
)
And finally, if you’re getting in to heavy envelope modulation (beyond just one or two parameters), you can also just send whole envelopes to the synth as a parameter. Here’s something I wrote up with a few tricks for doing that: https://scsynth.org/t/envelope-passing-for-synths-and-patterns/2048/6